ray

Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/ray.git

first

Commit a5d74cc6b7d90b0c280097b33705d2e7883317ec by SM <seb.michalk@gmail.com> on 2025-06-30 09:31:02 +0200
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..570ac99
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,83 @@
+# Makefile for JTAC Coordinate System Plugin
+# Cross-compilation for Windows using MinGW-w64
+
+# Compiler settings
+CC = x86_64-w64-mingw32-gcc
+CXX = x86_64-w64-mingw32-g++
+
+# Plugin name and output
+PLUGIN_NAME = JTACCoords
+OUTPUT_DIR = build
+PLUGIN_DIR = $(OUTPUT_DIR)/$(PLUGIN_NAME)
+PLUGIN_FILE = $(PLUGIN_DIR)/win_x64/$(PLUGIN_NAME).xpl
+
+# SDK paths
+SDK_DIR = SDK
+INCLUDE_DIRS = -I$(SDK_DIR)/CHeaders/XPLM -I$(SDK_DIR)/CHeaders/Widgets -I.
+LIB_DIR = $(SDK_DIR)/Libraries/Win
+LIBS = -L$(LIB_DIR) -lXPLM_64 -lXPWidgets_64
+
+# Compiler flags for C++
+CXXFLAGS = -std=c++11 -Wall -O2 -fPIC -DXPLM200=1 -DXPLM210=1 -DXPLM300=1 -DXPLM301=1 -DXPLM302=1 -DXPLM400=1
+CXXFLAGS += $(INCLUDE_DIRS)
+CXXFLAGS += -DIBM=1 -DWIN32=1 -D_WIN32=1
+
+# Linker flags for Windows DLL
+LDFLAGS = -shared -static-libgcc -static-libstdc++
+LDFLAGS += -Wl,--kill-at -Wl,--no-undefined
+LDFLAGS += $(LIBS)
+LDFLAGS += -lopengl32 -lgdi32 -lm
+
+# Source files
+SOURCES = probe.cpp
+
+# Object files
+OBJECTS = $(SOURCES:.cpp=.o)
+
+# Default target
+all: directories $(PLUGIN_FILE)
+
+# Create necessary directories
+directories:
+	@mkdir -p $(PLUGIN_DIR)/win_x64
+
+# Build the plugin
+$(PLUGIN_FILE): $(OBJECTS)
+	$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
+	@echo "JTAC Coordinate System Plugin built successfully: $@"
+
+# Compile source files
+%.o: %.cpp
+	$(CXX) $(CXXFLAGS) -c $< -o $@
+
+# Clean build files
+clean:
+	rm -f $(OBJECTS)
+	rm -rf $(OUTPUT_DIR)
+
+# Test compilation without linking
+test-compile:
+	$(CXX) $(CXXFLAGS) -c $(SOURCES)
+	@echo "Compilation test successful"
+
+# Development helpers
+debug: CXXFLAGS += -g -DDEBUG=1
+debug: directories $(PLUGIN_FILE)
+
+release: CXXFLAGS += -DNDEBUG=1 -s
+release: directories $(PLUGIN_FILE)
+
+# Check MinGW installation
+check-mingw:
+	@which x86_64-w64-mingw32-gcc > /dev/null || (echo "MinGW-w64 not found. Install with: sudo apt-get install mingw-w64" && exit 1)
+	@echo "MinGW-w64 found and ready for cross-compilation"
+
+# Installation helper
+install: $(PLUGIN_FILE)
+	@echo "Plugin built at: $(PLUGIN_FILE)"
+	@echo "Copy the entire $(PLUGIN_DIR) folder to your X-Plane 12/Resources/plugins/ directory"
+
+.PHONY: all clean directories test-compile debug release check-mingw install
+
+# Dependencies
+probe.o: probe.cpp
\ No newline at end of file
diff --git a/SDK/CHeaders/Widgets/XPStandardWidgets.h b/SDK/CHeaders/Widgets/XPStandardWidgets.h
new file mode 100644
index 0000000..1903e87
--- /dev/null
+++ b/SDK/CHeaders/Widgets/XPStandardWidgets.h
@@ -0,0 +1,556 @@
+#ifndef _XPStandardWidgets_h_
+#define _XPStandardWidgets_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPStandardWidgets
+ ***************************************************************************/
+/*
+ * ## THEORY OF OPERATION
+ * 
+ * The standard widgets are widgets built into the widgets library. While you
+ * can gain access to the widget function that drives them, you generally use
+ * them by calling XPCreateWidget and then listening for special messages,
+ * etc.
+ * 
+ * The standard widgets often send messages to themselves when the user
+ * performs an event; these messages are sent up the widget hierarchy until
+ * they are handled. So you can add a widget proc directly to a push button
+ * (for example) to intercept the message when it is clicked, or you can put
+ * one widget proc on a window for all of the push buttons in the window. Most
+ * of these messages contain the original widget ID as a parameter so you can
+ * know which widget is messaging no matter who it is sent to.
+ *
+ */
+
+#include "XPWidgetDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * MAIN WINDOW
+ ***************************************************************************/
+/*
+ * The main window widget class provides a "window" as the user knows it.
+ * These windows are draggable and can be selected. Use them to create
+ * floating windows and non-modal dialogs.
+ *
+ */
+
+
+#define xpWidgetClass_MainWindow 1
+
+/*
+ * Main Window Type Values
+ * 
+ * These type values are used to control the appearance of a main window.
+ *
+ */
+enum {
+    /* The standard main window; pin stripes on XP7, metal frame on XP 6.         */
+    xpMainWindowStyle_MainWindow             = 0,
+
+    /* A translucent dark gray window.                                            */
+    xpMainWindowStyle_Translucent            = 1,
+
+
+};
+
+/*
+ * Main Window Properties
+ *
+ */
+enum {
+    /* This property specifies the type of window.  Set to one of the main window *
+     * types above.                                                               */
+    xpProperty_MainWindowType                = 1100,
+
+    /* This property specifies whether the main window has close boxes in its     *
+     * corners.                                                                   */
+    xpProperty_MainWindowHasCloseBoxes       = 1200,
+
+
+};
+
+/*
+ * MainWindow Messages
+ *
+ */
+enum {
+    /* This message is sent when the close buttons for your window are pressed.   */
+    xpMessage_CloseButtonPushed              = 1200,
+
+
+};
+
+/***************************************************************************
+ * SUB WINDOW
+ ***************************************************************************/
+/*
+ * X-Plane dialogs are divided into separate areas; the sub window widgets
+ * allow you to make these areas. Create one main window and place several
+ * subwindows inside it. Then place your controls inside the subwindows.
+ *
+ */
+
+
+#define xpWidgetClass_SubWindow 2
+
+/*
+ * SubWindow Type Values
+ * 
+ * These values control the appearance of the subwindow.
+ *
+ */
+enum {
+    /* A panel that sits inside a main window.                                    */
+    xpSubWindowStyle_SubWindow               = 0,
+
+    /* A screen that sits inside a panel for showing text information.            */
+    xpSubWindowStyle_Screen                  = 2,
+
+    /* A list view for scrolling lists.                                           */
+    xpSubWindowStyle_ListView                = 3,
+
+
+};
+
+/*
+ * SubWindow Properties
+ *
+ */
+enum {
+    /* This property specifies the type of window.  Set to one of the subwindow   *
+     * types above.                                                               */
+    xpProperty_SubWindowType                 = 1200,
+
+
+};
+
+/***************************************************************************
+ * BUTTON
+ ***************************************************************************/
+/*
+ * The button class provides a number of different button styles and
+ * behaviors, including push buttons, radio buttons, check boxes, etc. The
+ * button label appears on or next to the button depending on the button's
+ * appearance or type.
+ * 
+ * The button's behavior is a separate property that dictates who it
+ * highlights and what kinds of messages it sends. Since behavior and type are
+ * different, you can do strange things like make check boxes that act as push
+ * buttons or push buttons with radio button behavior.
+ * 
+ * In X-Plane 6 there were no check box graphics. The result is the following
+ * behavior: in X-Plane
+ * 6 all check box and radio buttons are round (radio-button style) buttons;
+ *   in X-Plane 7 they are all square (check-box style) buttons. In a future
+ *   version of X-Plane, the xpButtonBehavior enums will provide the correct
+ *   graphic (check box or radio button) giving the expected result.
+ *
+ */
+
+
+#define xpWidgetClass_Button 3
+
+/*
+ * Button Types
+ * 
+ * These define the visual appearance of buttons but not how they respond to
+ * the mouse.
+ *
+ */
+enum {
+    /* This is a standard push button, like an 'OK' or 'Cancel' button in a dialog*
+     * box.                                                                       */
+    xpPushButton                             = 0,
+
+    /* A check box or radio button.  Use this and the button behaviors below to   *
+     * get the desired behavior.                                                  */
+    xpRadioButton                            = 1,
+
+    /* A window close box.                                                        */
+    xpWindowCloseBox                         = 3,
+
+    /* A small down arrow.                                                        */
+    xpLittleDownArrow                        = 5,
+
+    /* A small up arrow.                                                          */
+    xpLittleUpArrow                          = 6,
+
+
+};
+
+/*
+ * Button Behavior Values
+ * 
+ * These define how the button responds to mouse clicks.
+ *
+ */
+enum {
+    /* Standard push button behavior. The button highlights while the mouse is    *
+     * clicked over it and unhighlights when the mouse is moved outside of it or  *
+     * released. If the mouse is released over the button, the                    *
+     * xpMsg_PushButtonPressed message is sent.                                   */
+    xpButtonBehaviorPushButton               = 0,
+
+    /* Check box behavior. The button immediately toggles its value when the mouse*
+     * is clicked and sends out a xpMsg_ButtonStateChanged message.               */
+    xpButtonBehaviorCheckBox                 = 1,
+
+    /* Radio button behavior. The button immediately sets its state to one and    *
+     * sends out a xpMsg_ButtonStateChanged message if it was not already set to  *
+     * one. You must turn off other radio buttons in a group in your code.        */
+    xpButtonBehaviorRadioButton              = 2,
+
+
+};
+
+/*
+ * Button Properties
+ *
+ */
+enum {
+    /* This property sets the visual type of button.  Use one of the button types *
+     * above.                                                                     */
+    xpProperty_ButtonType                    = 1300,
+
+    /* This property sets the button's behavior.  Use one of the button behaviors *
+     * above.                                                                     */
+    xpProperty_ButtonBehavior                = 1301,
+
+    /* This property tells whether a check box or radio button is "checked" or    *
+     * not. Not used for push buttons.                                            */
+    xpProperty_ButtonState                   = 1302,
+
+
+};
+
+/*
+ * Button Messages
+ * 
+ * These messages are sent by the button to itself and then up the widget
+ * chain when the button is clicked. (You may intercept them by providing a
+ * widget handler for the button itself or by providing a handler in a parent
+ * widget.)
+ *
+ */
+enum {
+    /* This message is sent when the user completes a click and release in a      *
+     * button with push button behavior. Parameter one of the message is the      *
+     * widget ID of the button. This message is dispatched up the widget          *
+     * hierarchy.                                                                 */
+    xpMsg_PushButtonPressed                  = 1300,
+
+    /* This message is sent when a button is clicked that has radio button or     *
+     * check box behavior and its value changes. (Note that if the value changes  *
+     * by setting a property you do not receive this message!) Parameter one is   *
+     * the widget ID of the button, parameter 2 is the new state value, either    *
+     * zero or one. This message is dispatched up the widget hierarchy.           */
+    xpMsg_ButtonStateChanged                 = 1301,
+
+
+};
+
+/***************************************************************************
+ * TEXT FIELD
+ ***************************************************************************/
+/*
+ * The text field widget provides an editable text field including mouse
+ * selection and keyboard navigation. The contents of the text field are its
+ * descriptor. (The descriptor changes as the user types.)
+ * 
+ * The text field can have a number of types, that affect the visual layout of
+ * the text field. The text field sends messages to itself so you may control
+ * its behavior.
+ * 
+ * If you need to filter keystrokes, add a new handler and intercept the key
+ * press message. Since key presses are passed by pointer, you can modify the
+ * keystroke and pass it through to the text field widget.
+ * 
+ * WARNING: in X-Plane before 7.10 (including 6.70) null characters could
+ * crash X-Plane. To prevent this, wrap this object with a filter function
+ * (more instructions can be found on the SDK website).
+ *
+ */
+
+
+#define xpWidgetClass_TextField 4
+
+/*
+ * Text Field Type Values
+ * 
+ * These control the look of the text field.
+ *
+ */
+enum {
+    /* A field for text entry.                                                    */
+    xpTextEntryField                         = 0,
+
+    /* A transparent text field. The user can type and the text is drawn, but no  *
+     * background is drawn. You can draw your own background by adding a widget   *
+     * handler and prehandling the draw message.                                  */
+    xpTextTransparent                        = 3,
+
+    /* A translucent edit field, dark gray.                                       */
+    xpTextTranslucent                        = 4,
+
+
+};
+
+/*
+ * Text Field Properties
+ *
+ */
+enum {
+    /* This is the character position the selection starts at, zero based. If it  *
+     * is the same as the end insertion point, the insertion point is not a       *
+     * selection.                                                                 */
+    xpProperty_EditFieldSelStart             = 1400,
+
+    /* This is the character position of the end of the selection.                */
+    xpProperty_EditFieldSelEnd               = 1401,
+
+    /* This is the character position a drag was started at if the user is        *
+     * dragging to select text, or -1 if a drag is not in progress.               */
+    xpProperty_EditFieldSelDragStart         = 1402,
+
+    /* This is the type of text field to display, from the above list.            */
+    xpProperty_TextFieldType                 = 1403,
+
+    /* Set this property to 1 to password protect the field. Characters will be   *
+     * drawn as *s even though the descriptor will contain plain-text.            */
+    xpProperty_PasswordMode                  = 1404,
+
+    /* The max number of characters you can enter, if limited.  Zero means        *
+     * unlimited.                                                                 */
+    xpProperty_MaxCharacters                 = 1405,
+
+    /* The first visible character on the left.  This effectively scrolls the text*
+     * field.                                                                     */
+    xpProperty_ScrollPosition                = 1406,
+
+    /* The font to draw the field's text with.  (An XPLMFontID.)                  */
+    xpProperty_Font                          = 1407,
+
+    /* This is the active side of the insert selection.  (Internal)               */
+    xpProperty_ActiveEditSide                = 1408,
+
+
+};
+
+/*
+ * Text Field Messages
+ *
+ */
+enum {
+    /* The text field sends this message to itself when its text changes. It sends*
+     * the message up the call chain; param1 is the text field's widget ID.       */
+    xpMsg_TextFieldChanged                   = 1400,
+
+
+};
+
+/***************************************************************************
+ * SCROLL BAR
+ ***************************************************************************/
+/*
+ * A standard scroll bar or slider control. The scroll bar has a minimum,
+ * maximum and current value that is updated when the user drags it. The
+ * scroll bar sends continuous messages as it is dragged.
+ *
+ */
+
+
+#define xpWidgetClass_ScrollBar 5
+
+/*
+ * Scroll Bar Type Values
+ * 
+ * This defines how the scroll bar looks.
+ *
+ */
+enum {
+    /* A standard X-Plane scroll bar (with arrows on the ends).                   */
+    xpScrollBarTypeScrollBar                 = 0,
+
+    /* A slider, no arrows.                                                       */
+    xpScrollBarTypeSlider                    = 1,
+
+
+};
+
+/*
+ * Scroll Bar Properties
+ *
+ */
+enum {
+    /* The current position of the thumb (in between the min and max, inclusive)  */
+    xpProperty_ScrollBarSliderPosition       = 1500,
+
+    /* The value the scroll bar has when the thumb is in the lowest position.     */
+    xpProperty_ScrollBarMin                  = 1501,
+
+    /* The value the scroll bar has when the thumb is in the highest position.    */
+    xpProperty_ScrollBarMax                  = 1502,
+
+    /* How many units to move the scroll bar when clicking next to the thumb. The *
+     * scroll bar always moves one unit when the arrows are clicked.              */
+    xpProperty_ScrollBarPageAmount           = 1503,
+
+    /* The type of scrollbar from the enums above.                                */
+    xpProperty_ScrollBarType                 = 1504,
+
+    /* Used internally.                                                           */
+    xpProperty_ScrollBarSlop                 = 1505,
+
+
+};
+
+/*
+ * Scroll Bar Messages
+ *
+ */
+enum {
+    /* The scroll bar sends this message when the slider position changes. It     *
+     * sends the message up the call chain; param1 is the scroll bar widget ID.   */
+    xpMsg_ScrollBarSliderPositionChanged     = 1500,
+
+
+};
+
+/***************************************************************************
+ * CAPTION
+ ***************************************************************************/
+/*
+ * A caption is a simple widget that shows its descriptor as a string, useful
+ * for labeling parts of a window. It always shows its descriptor as its
+ * string and is otherwise transparent.
+ *
+ */
+
+
+#define xpWidgetClass_Caption 6
+
+/*
+ * Caption Properties
+ *
+ */
+enum {
+    /* This property specifies whether the caption is lit; use lit captions       *
+     * against screens.                                                           */
+    xpProperty_CaptionLit                    = 1600,
+
+
+};
+
+/***************************************************************************
+ * GENERAL GRAPHICS
+ ***************************************************************************/
+/*
+ * The general graphics widget can show one of many icons available from
+ * X-Plane.
+ *
+ */
+
+
+#define xpWidgetClass_GeneralGraphics 7
+
+/*
+ * General Graphics Types Values
+ * 
+ * These define the icon for the general graphics.
+ *
+ */
+enum {
+    xpShip                                   = 4,
+
+    xpILSGlideScope                          = 5,
+
+    xpMarkerLeft                             = 6,
+
+    xp_Airport                               = 7,
+
+    xpNDB                                    = 8,
+
+    xpVOR                                    = 9,
+
+    xpRadioTower                             = 10,
+
+    xpAircraftCarrier                        = 11,
+
+    xpFire                                   = 12,
+
+    xpMarkerRight                            = 13,
+
+    xpCustomObject                           = 14,
+
+    xpCoolingTower                           = 15,
+
+    xpSmokeStack                             = 16,
+
+    xpBuilding                               = 17,
+
+    xpPowerLine                              = 18,
+
+    xpVORWithCompassRose                     = 19,
+
+    xpOilPlatform                            = 21,
+
+    xpOilPlatformSmall                       = 22,
+
+    xpWayPoint                               = 23,
+
+
+};
+
+/*
+ * General Graphics Properties
+ *
+ */
+enum {
+    /* This property controls the type of icon that is drawn.                     */
+    xpProperty_GeneralGraphicsType           = 1700,
+
+
+};
+
+/***************************************************************************
+ * PROGRESS INDICATOR
+ ***************************************************************************/
+/*
+ * This widget implements a progress indicator as seen when X-Plane starts up.
+ *
+ */
+
+#define xpWidgetClass_Progress 8
+
+/*
+ * Progress Indicator Properties
+ *
+ */
+enum {
+    /* This is the current value of the progress indicator.                       */
+    xpProperty_ProgressPosition              = 1800,
+
+    /* This is the minimum value, equivalent to 0% filled.                        */
+    xpProperty_ProgressMin                   = 1801,
+
+    /* This is the maximum value, equivalent to 100% filled.                      */
+    xpProperty_ProgressMax                   = 1802,
+
+
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/Widgets/XPUIGraphics.h b/SDK/CHeaders/Widgets/XPUIGraphics.h
new file mode 100644
index 0000000..83ed302
--- /dev/null
+++ b/SDK/CHeaders/Widgets/XPUIGraphics.h
@@ -0,0 +1,353 @@
+#ifndef _XPUIGraphics_h_
+#define _XPUIGraphics_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPUIGraphics
+ ***************************************************************************/
+
+#include "XPWidgetDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * UI GRAPHICS
+ ***************************************************************************/
+
+/*
+ * XPWindowStyle
+ * 
+ * There are a few built-in window styles in X-Plane that you can use.
+ * 
+ * Note that X-Plane 6 does not offer real shadow-compositing; you must make
+ * sure to put a window on top of another window of the right style to make
+ * the shadows work, etc. This applies to elements with insets and shadows.
+ * The rules are:
+ * 
+ * Sub windows must go on top of main windows, and screens and list views on
+ * top of subwindows. Only help and main windows can be over the main screen.
+ * 
+ * With X-Plane 7 any window or element may be placed over any other element.
+ * 
+ * Some windows are scaled by stretching, some by repeating. The drawing
+ * routines know which scaling method to use. The list view cannot be rescaled
+ * in X-Plane 6 because it has both a repeating pattern and a gradient in one
+ * element. All other elements can be rescaled.
+ *
+ */
+enum {
+    /* An LCD screen that shows help.                                             */
+    xpWindow_Help                            = 0,
+
+    /* A dialog box window.                                                       */
+    xpWindow_MainWindow                      = 1,
+
+    /* A panel or frame within a dialog box window.                               */
+    xpWindow_SubWindow                       = 2,
+
+    /* An LCD screen within a panel to hold text displays.                        */
+    xpWindow_Screen                          = 4,
+
+    /* A list view within a panel for scrolling file names, etc.                  */
+    xpWindow_ListView                        = 5,
+
+
+};
+typedef int XPWindowStyle;
+
+/*
+ * XPDrawWindow
+ * 
+ * This routine draws a window of the given dimensions at the given offset on
+ * the virtual screen in a given style. The window is automatically scaled as
+ * appropriate using a bitmap scaling technique (scaling or repeating) as
+ * appropriate to the style.
+ *
+ */
+WIDGET_API void       XPDrawWindow(
+                         int                  inX1,
+                         int                  inY1,
+                         int                  inX2,
+                         int                  inY2,
+                         XPWindowStyle        inStyle);
+
+/*
+ * XPGetWindowDefaultDimensions
+ * 
+ * This routine returns the default dimensions for a window. Output is either
+ * a minimum or fixed value depending on whether the window is scalable.
+ *
+ */
+WIDGET_API void       XPGetWindowDefaultDimensions(
+                         XPWindowStyle        inStyle,
+                         int *                outWidth,               /* Can be NULL */
+                         int *                outHeight);             /* Can be NULL */
+
+/*
+ * XPElementStyle
+ * 
+ * Elements are individually drawable UI things like push buttons, etc. The
+ * style defines what kind of element you are drawing. Elements can be
+ * stretched in one or two dimensions (depending on the element). Some
+ * elements can be lit.
+ * 
+ * In X-Plane 6 some elements must be drawn over metal. Some are scalable and
+ * some are not. Any element can be drawn anywhere in X-Plane 7.
+ * 
+ * Scalable Axis Required Background
+ *
+ */
+enum {
+    /* x      metal                                                               */
+    xpElement_TextField                      = 6,
+
+    /* none     metal                                                             */
+    xpElement_CheckBox                       = 9,
+
+    /* none     metal                                                             */
+    xpElement_CheckBoxLit                    = 10,
+
+    /* none     window header                                                     */
+    xpElement_WindowCloseBox                 = 14,
+
+    /* none     window header                                                     */
+    xpElement_WindowCloseBoxPressed          = 15,
+
+    /* x     metal                                                                */
+    xpElement_PushButton                     = 16,
+
+    /* x     metal                                                                */
+    xpElement_PushButtonLit                  = 17,
+
+    /* none     any                                                               */
+    xpElement_OilPlatform                    = 24,
+
+    /* none     any                                                               */
+    xpElement_OilPlatformSmall               = 25,
+
+    /* none     any                                                               */
+    xpElement_Ship                           = 26,
+
+    /* none     any                                                               */
+    xpElement_ILSGlideScope                  = 27,
+
+    /* none     any                                                               */
+    xpElement_MarkerLeft                     = 28,
+
+    /* none     any                                                               */
+    xpElement_Airport                        = 29,
+
+    /* none     any                                                               */
+    xpElement_Waypoint                       = 30,
+
+    /* none     any                                                               */
+    xpElement_NDB                            = 31,
+
+    /* none     any                                                               */
+    xpElement_VOR                            = 32,
+
+    /* none     any                                                               */
+    xpElement_RadioTower                     = 33,
+
+    /* none     any                                                               */
+    xpElement_AircraftCarrier                = 34,
+
+    /* none     any                                                               */
+    xpElement_Fire                           = 35,
+
+    /* none     any                                                               */
+    xpElement_MarkerRight                    = 36,
+
+    /* none     any                                                               */
+    xpElement_CustomObject                   = 37,
+
+    /* none     any                                                               */
+    xpElement_CoolingTower                   = 38,
+
+    /* none     any                                                               */
+    xpElement_SmokeStack                     = 39,
+
+    /* none     any                                                               */
+    xpElement_Building                       = 40,
+
+    /* none     any                                                               */
+    xpElement_PowerLine                      = 41,
+
+    /* none     metal                                                             */
+    xpElement_CopyButtons                    = 45,
+
+    /* none     metal                                                             */
+    xpElement_CopyButtonsWithEditingGrid     = 46,
+
+    /* x, y     metal                                                             */
+    xpElement_EditingGrid                    = 47,
+
+    /* THIS CAN PROBABLY BE REMOVED                                               */
+    xpElement_ScrollBar                      = 48,
+
+    /* none     any                                                               */
+    xpElement_VORWithCompassRose             = 49,
+
+    /* none     metal                                                             */
+    xpElement_Zoomer                         = 51,
+
+    /* x, y     metal                                                             */
+    xpElement_TextFieldMiddle                = 52,
+
+    /* none     metal                                                             */
+    xpElement_LittleDownArrow                = 53,
+
+    /* none     metal                                                             */
+    xpElement_LittleUpArrow                  = 54,
+
+    /* none     metal                                                             */
+    xpElement_WindowDragBar                  = 61,
+
+    /* none     metal                                                             */
+    xpElement_WindowDragBarSmooth            = 62,
+
+
+};
+typedef int XPElementStyle;
+
+/*
+ * XPDrawElement
+ * 
+ * XPDrawElement draws a given element at an offset on the virtual screen in
+ * set dimensions. Even if the element is not scalable, it will be scaled if
+ * the width and height do not match the preferred dimensions; it'll just look
+ * ugly. Pass inLit to see the lit version of the element; if the element
+ * cannot be lit this is ignored.
+ *
+ */
+WIDGET_API void       XPDrawElement(
+                         int                  inX1,
+                         int                  inY1,
+                         int                  inX2,
+                         int                  inY2,
+                         XPElementStyle       inStyle,
+                         int                  inLit);
+
+/*
+ * XPGetElementDefaultDimensions
+ * 
+ * This routine returns the recommended or minimum dimensions of a given UI
+ * element. outCanBeLit tells whether the element has both a lit and unlit
+ * state. Pass NULL to not receive any of these parameters.
+ *
+ */
+WIDGET_API void       XPGetElementDefaultDimensions(
+                         XPElementStyle       inStyle,
+                         int *                outWidth,               /* Can be NULL */
+                         int *                outHeight,              /* Can be NULL */
+                         int *                outCanBeLit);           /* Can be NULL */
+
+/*
+ * XPTrackStyle
+ * 
+ * A track is a UI element that displays a value vertically or horizontally.
+ * X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars.
+ * Tracks can be displayed either horizontally or vertically; tracks will
+ * choose their own layout based on the larger dimension of their dimensions
+ * (e.g. they know if they are tall or wide). Sliders may be lit or unlit
+ * (showing the user manipulating them).
+ * 
+ * - ScrollBar: this is a standard scroll bar with arrows and a thumb to drag.
+ * - Slider: this is a simple track with a ball in the middle that can be
+ *   slid.
+ * - Progress: this is a progress indicator showing how a long task is going.
+ *
+ */
+enum {
+    /*  not over metal can be lit  can be rotated                                 */
+    xpTrack_ScrollBar                        = 0,
+
+    /*  over metal  can be lit  can be rotated                                    */
+    xpTrack_Slider                           = 1,
+
+    /*  over metal  cannot be lit cannot be rotated                               */
+    xpTrack_Progress                         = 2,
+
+
+};
+typedef int XPTrackStyle;
+
+/*
+ * XPDrawTrack
+ * 
+ * This routine draws a track. You pass in the track dimensions and size; the
+ * track picks the optimal orientation for these dimensions. Pass in the
+ * track's minimum current and maximum values; the indicator will be
+ * positioned appropriately. You can also specify whether the track is lit or
+ * not.
+ *
+ */
+WIDGET_API void       XPDrawTrack(
+                         int                  inX1,
+                         int                  inY1,
+                         int                  inX2,
+                         int                  inY2,
+                         int                  inMin,
+                         int                  inMax,
+                         int                  inValue,
+                         XPTrackStyle         inTrackStyle,
+                         int                  inLit);
+
+/*
+ * XPGetTrackDefaultDimensions
+ * 
+ * This routine returns a track's default smaller dimension; all tracks are
+ * scalable in the larger dimension. It also returns whether a track can be
+ * lit.
+ *
+ */
+WIDGET_API void       XPGetTrackDefaultDimensions(
+                         XPTrackStyle         inStyle,
+                         int *                outWidth,
+                         int *                outCanBeLit);
+
+/*
+ * XPGetTrackMetrics
+ * 
+ * This routine returns the metrics of a track. If you want to write UI code
+ * to manipulate a track, this routine helps you know where the mouse
+ * locations are. For most other elements, the rectangle the element is drawn
+ * in is enough information. However, the scrollbar drawing routine does some
+ * automatic placement; this routine lets you know where things ended up. You
+ * pass almost everything you would pass to the draw routine. You get out the
+ * orientation, and other useful stuff.
+ * 
+ * Besides orientation, you get five dimensions for the five parts of a
+ * scrollbar, which are the down button, down area (area before the thumb),
+ * the thumb, and the up area and button. For horizontal scrollers, the left
+ * button decreases; for vertical scrollers, the top button decreases.
+ *
+ */
+WIDGET_API void       XPGetTrackMetrics(
+                         int                  inX1,
+                         int                  inY1,
+                         int                  inX2,
+                         int                  inY2,
+                         int                  inMin,
+                         int                  inMax,
+                         int                  inValue,
+                         XPTrackStyle         inTrackStyle,
+                         int *                outIsVertical,
+                         int *                outDownBtnSize,
+                         int *                outDownPageSize,
+                         int *                outThumbSize,
+                         int *                outUpPageSize,
+                         int *                outUpBtnSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/Widgets/XPWidgetDefs.h b/SDK/CHeaders/Widgets/XPWidgetDefs.h
new file mode 100644
index 0000000..a4fc1ba
--- /dev/null
+++ b/SDK/CHeaders/Widgets/XPWidgetDefs.h
@@ -0,0 +1,472 @@
+#ifndef _XPWidgetDefs_h_
+#define _XPWidgetDefs_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPWidgetDefs
+ ***************************************************************************/
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if APL
+	#if XPWIDGETS
+        #if __GNUC__ >= 4
+            #define WIDGET_API __attribute__((visibility("default")))
+        #elif __MACH__
+			#define WIDGET_API
+		#else
+			#define WIDGET_API __declspec(dllexport)
+		#endif
+	#else
+		#define WIDGET_API
+	#endif
+#elif IBM
+	#if XPWIDGETS
+		#define WIDGET_API __declspec(dllexport)
+	#else
+		#define WIDGET_API __declspec(dllimport)
+	#endif
+#elif LIN
+	#if XPWIDGETS
+		#if __GNUC__ >= 4
+			#define WIDGET_API __attribute__((visibility("default")))
+		#else
+			#define WIDGET_API
+		#endif
+	#else
+		#define WIDGET_API
+	#endif
+#else
+#pragma error "Platform not defined!"
+#endif
+	/***************************************************************************
+ * WIDGET DEFINITIONS
+ ***************************************************************************/
+/*
+ * A widget is a call-back driven screen entity like a push-button, window,
+ * text entry field, etc.
+ * 
+ * Use the widget API to create widgets of various classes. You can nest them
+ * into trees of widgets to create complex user interfaces.
+ *
+ */
+
+
+/*
+ * XPWidgetID
+ * 
+ * A Widget ID is an opaque unique non-zero handle identifying your widget.
+ * Use 0 to specify "no widget". This type is defined as wide enough to hold a
+ * pointer. You receive a widget ID when you create a new widget and then use
+ * that widget ID to further refer to the widget.
+ *
+ */
+typedef void * XPWidgetID;
+
+/*
+ * XPWidgetPropertyID
+ * 
+ * Properties are values attached to instances of your widgets. A property is
+ * identified by a 32-bit ID and its value is the width of a pointer.
+ * 
+ * Each widget instance may have a property or not have it. When you set a
+ * property on a widget for the first time, the property is added to the
+ * widget; it then stays there for the life of the widget.
+ * 
+ * Some property IDs are predefined by the widget package; you can make up
+ * your own property IDs as well.
+ *
+ */
+enum {
+    /* A window's refcon is an opaque value used by client code to find other data*
+     * based on it.                                                               */
+    xpProperty_Refcon                        = 0,
+
+    /* These properties are used by the utilities to implement dragging.          */
+    xpProperty_Dragging                      = 1,
+
+    xpProperty_DragXOff                      = 2,
+
+    xpProperty_DragYOff                      = 3,
+
+    /* Is the widget highlighted?  (For widgets that support this kind of thing.) */
+    xpProperty_Hilited                       = 4,
+
+    /* Is there a C++ object attached to this widget?                             */
+    xpProperty_Object                        = 5,
+
+    /* If this property is 1, the widget package will use OpenGL to restrict      *
+     * drawing to the Widget's exposed rectangle.                                 */
+    xpProperty_Clip                          = 6,
+
+    /* Is this widget enabled (for those that have a disabled state too)?         */
+    xpProperty_Enabled                       = 7,
+
+    /* NOTE: Property IDs 1 - 999 are reserved for the widgets library.           *
+     *                                                                            *
+     * NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes*
+     * provided with the library.                                                 *
+     *                                                                            *
+     * Properties 1000 - 1099 are for widget class 0, 1100 - 1199 for widget class*
+     * 1, etc.                                                                    */
+    xpProperty_UserStart                     = 10000,
+
+
+};
+typedef int XPWidgetPropertyID;
+
+/*
+ * XPMouseState_t
+ * 
+ * When the mouse is clicked or dragged, a pointer to this structure is passed
+ * to your widget function.
+ *
+ */
+typedef struct {
+     int                       x;
+     int                       y;
+    /* Mouse button number, left = 0 (right button not yet supported.             */
+     int                       button;
+#if defined(XPLM200)
+    /* Scroll wheel delta (button in this case would be the wheel axis number).   */
+     int                       delta;
+#endif /* XPLM200 */
+} XPMouseState_t;
+
+/*
+ * XPKeyState_t
+ * 
+ * When a key is pressed, a pointer to this struct is passed to your widget
+ * function.
+ *
+ */
+typedef struct {
+    /* The ASCII key that was pressed.  WARNING: this may be 0 for some non-ASCII *
+     * key sequences.                                                             */
+     char                      key;
+    /* The flags.  Make sure to check this if you only want key-downs!            */
+     XPLMKeyFlags              flags;
+    /* The virtual key code for the key                                           */
+     char                      vkey;
+} XPKeyState_t;
+
+/*
+ * XPWidgetGeometryChange_t
+ * 
+ * This structure contains the deltas for your widget's geometry when it
+ * changes.
+ *
+ */
+typedef struct {
+     int                       dx;
+    /* +Y = the widget moved up                                                   */
+     int                       dy;
+     int                       dwidth;
+     int                       dheight;
+} XPWidgetGeometryChange_t;
+
+/*
+ * XPDispatchMode
+ * 
+ * The dispatching modes describe how the widgets library sends out messages. 
+ * Currently there are three modes:
+ *
+ */
+enum {
+    /* The message will only be sent to the target widget.                        */
+    xpMode_Direct                            = 0,
+
+    /* The message is sent to the target widget, then up the chain of parents     *
+     * until the message is handled or a parentless widget is reached.            */
+    xpMode_UpChain                           = 1,
+
+    /* The message is sent to the target widget and then all of its children      *
+     * recursively depth-first.                                                   */
+    xpMode_Recursive                         = 2,
+
+    /* The message is sent just to the target, but goes to every callback, even if*
+     * it is handled.                                                             */
+    xpMode_DirectAllCallbacks                = 3,
+
+    /* The message is only sent to the very first handler even if it is not       *
+     * accepted. (This is really only useful for some internal widget library     *
+     * functions.)                                                                */
+    xpMode_Once                              = 4,
+
+
+};
+typedef int XPDispatchMode;
+
+/*
+ * XPWidgetClass
+ * 
+ * Widget classes define predefined widget types. A widget class basically
+ * specifies from a library the widget function to be used for the widget.
+ * Most widgets can be made right from classes.
+ *
+ */
+typedef int XPWidgetClass;
+
+/* An unspecified widget class.  Other widget classes are in                  *
+ * XPStandardWidgets.h                                                        */
+#define xpWidgetClass_None   0
+
+/***************************************************************************
+ * WIDGET MESSAGES
+ ***************************************************************************/
+
+/*
+ * XPWidgetMessage
+ * 
+ * Widgets receive 32-bit messages indicating what action is to be taken or
+ * notifications of events. The list of messages may be expanded.
+ *
+ */
+enum {
+    /* No message, should not be sent.                                            */
+    xpMsg_None                               = 0,
+
+    /* The create message is sent once per widget that is created with your widget*
+     * function and once for any widget that has your widget function attached.   *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: 1 if you are being added as a subclass, 0 if the widget is first  *
+     * being created.                                                             */
+    xpMsg_Create                             = 1,
+
+    /* The destroy message is sent once for each message that is destroyed that   *
+     * has your widget function.                                                  *
+     *                                                                            *
+     * Dispatching: Direct for all                                                *
+     *                                                                            *
+     * Param 1: 1 if being deleted by a recursive delete to the parent, 0 for     *
+     * explicit deletion.                                                         */
+    xpMsg_Destroy                            = 2,
+
+    /* The paint message is sent to your widget to draw itself. The paint message *
+     * is the bare-bones message; in response you must draw yourself, draw your   *
+     * children, set up clipping and culling, check for visibility, etc. If you   *
+     * don't want to do all of this, ignore the paint message and a draw message  *
+     * (see below) will be sent to you.                                           *
+     *                                                                            *
+     * Dispatching: Direct                                                        */
+    xpMsg_Paint                              = 3,
+
+    /* The draw message is sent to your widget when it is time to draw yourself.  *
+     * OpenGL will be set up to draw in 2-d global screen coordinates, but you    *
+     * should use the XPLM to set up OpenGL state.                                *
+     *                                                                            *
+     * Dispatching: Direct                                                        */
+    xpMsg_Draw                               = 4,
+
+    /* The key press message is sent once per key that is pressed. The first      *
+     * parameter is the type of key code (integer or char) and the second is the  *
+     * code itself. By handling this event, you consume the key stroke.           *
+     *                                                                            *
+     * Handling this message 'consumes' the keystroke; not handling it passes it  *
+     * to your parent widget.                                                     *
+     *                                                                            *
+     * Dispatching: Up Chain                                                      *
+     *                                                                            *
+     * Param 1: A pointer to an XPKeyState_t structure with the keystroke.        */
+    xpMsg_KeyPress                           = 5,
+
+    /* Keyboard focus is being given to you. By handling this message you accept  *
+     * keyboard focus. The first parameter will be one if a child of yours gave up*
+     * focus to you, 0 if someone set focus on you explicitly.                    *
+     *                                                                            *
+     * Handling this message accepts focus; not handling refuses focus.           *
+     *                                                                            *
+     * Dispatching: direct                                                        *
+     *                                                                            *
+     * Param 1: 1 if you are gaining focus because your child is giving it up, 0  *
+     * if someone is explicitly giving you focus.                                 */
+    xpMsg_KeyTakeFocus                       = 6,
+
+    /* Keyboard focus is being taken away from you. The first parameter will be 1 *
+     * if you are losing focus because another widget is taking it, or 0 if       *
+     * someone called the API to make you lose focus explicitly.                  *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: 1 if focus is being taken by another widget, 0 if code requested  *
+     * to remove focus.                                                           */
+    xpMsg_KeyLoseFocus                       = 7,
+
+    /* You receive one mousedown event per click with a mouse-state structure     *
+     * pointed to by parameter 1. By accepting this you eat the click, otherwise  *
+     * your parent gets it. You will not receive drag and mouse up messages if you*
+     * do not accept the down message.                                            *
+     *                                                                            *
+     * Handling this message consumes the mouse click, not handling it passes it  *
+     * to the next widget. You can act 'transparent' as a window by never handling*
+     * moues clicks to certain areas.                                             *
+     *                                                                            *
+     * Dispatching: Up chain NOTE: Technically this is direct dispatched, but the *
+     * widgets library will ship it to each widget until one consumes the click,  *
+     * making it effectively "up chain".                                          *
+     *                                                                            *
+     * Param 1: A pointer to an XPMouseState_t containing the mouse status.       */
+    xpMsg_MouseDown                          = 8,
+
+    /* You receive a series of mouse drag messages (typically one per frame in the*
+     * sim) as the mouse is moved once you have accepted a mouse down message.    *
+     * Parameter one points to a mouse-state structure describing the mouse       *
+     * location. You will continue to receive these until the mouse button is     *
+     * released. You may receive multiple mouse state messages with the same mouse*
+     * position. You will receive mouse drag events even if the mouse is dragged  *
+     * out of your current or original bounds at the time of the mouse down.      *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: A pointer to an XPMouseState_t containing the mouse status.       */
+    xpMsg_MouseDrag                          = 9,
+
+    /* The mouseup event is sent once when the mouse button is released after a   *
+     * drag or click. You only receive this message if you accept the mouseDown   *
+     * message. Parameter one points to a mouse state structure.                  *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: A pointer to an XPMouseState_t containing the mouse status.       */
+    xpMsg_MouseUp                            = 10,
+
+    /* Your geometry or a child's geometry is being changed.                      *
+     *                                                                            *
+     * Dispatching: Up chain                                                      *
+     *                                                                            *
+     * Param 1: The widget ID of the original reshaped target.                    *
+     *                                                                            *
+     * Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the     *
+     * change.                                                                    */
+    xpMsg_Reshape                            = 11,
+
+    /* Your exposed area has changed.                                             *
+     *                                                                            *
+     * Dispatching: Direct                                                        */
+    xpMsg_ExposedChanged                     = 12,
+
+    /* A child has been added to you. The child's ID is passed in parameter one.  *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: The Widget ID of the child being added.                           */
+    xpMsg_AcceptChild                        = 13,
+
+    /* A child has been removed from you. The child's ID is passed in parameter   *
+     * one.                                                                       *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: The Widget ID of the child being removed.                         */
+    xpMsg_LoseChild                          = 14,
+
+    /* You now have a new parent, or have no parent. The parent's ID is passed in,*
+     * or 0 for no parent.                                                        *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: The Widget ID of your parent                                      */
+    xpMsg_AcceptParent                       = 15,
+
+    /* You or a child has been shown. Note that this does not include you being   *
+     * shown because your parent was shown, you were put in a new parent, your    *
+     * root was shown, etc.                                                       *
+     *                                                                            *
+     * Dispatching: Up chain                                                      *
+     *                                                                            *
+     * Param 1: The widget ID of the shown widget.                                */
+    xpMsg_Shown                              = 16,
+
+    /* You have been hidden. See limitations above.                               *
+     *                                                                            *
+     * Dispatching: Up chain                                                      *
+     *                                                                            *
+     * Param 1: The widget ID of the hidden widget.                               */
+    xpMsg_Hidden                             = 17,
+
+    /* Your descriptor has changed.                                               *
+     *                                                                            *
+     * Dispatching: Direct                                                        */
+    xpMsg_DescriptorChanged                  = 18,
+
+    /* A property has changed. Param 1 contains the property ID.                  *
+     *                                                                            *
+     * Dispatching: Direct                                                        *
+     *                                                                            *
+     * Param 1: The Property ID being changed.                                    *
+     *                                                                            *
+     * Param 2: The new property value                                            */
+    xpMsg_PropertyChanged                    = 19,
+
+#if defined(XPLM200)
+    /* The mouse wheel has moved.                                                 *
+     *                                                                            *
+     * Return 1 to consume the mouse wheel move, or 0 to pass the message to a    *
+     * parent. Dispatching: Up chain                                              *
+     *                                                                            *
+     * Param 1: A pointer to an XPMouseState_t containing the mouse status.       */
+    xpMsg_MouseWheel                         = 20,
+
+#endif /* XPLM200 */
+#if defined(XPLM200)
+    /* The cursor is over your widget. If you consume this message, change the    *
+     * XPLMCursorStatus value to indicate the desired result, with the same rules *
+     * as in XPLMDisplay.h.                                                       *
+     *                                                                            *
+     * Return 1 to consume this message, 0 to pass it on.                         *
+     *                                                                            *
+     * Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct       *
+     * containing the mouse status.                                               *
+     *                                                                            *
+     * Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result   *
+     * you desire.                                                                */
+    xpMsg_CursorAdjust                       = 21,
+
+#endif /* XPLM200 */
+    /* NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes *
+     * provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 *
+     * for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. */
+    xpMsg_UserStart                          = 10000,
+
+
+};
+typedef int XPWidgetMessage;
+
+/***************************************************************************
+ * WIDGET CALLBACK FUNCTION
+ ***************************************************************************/
+
+/*
+ * XPWidgetFunc_t
+ * 
+ * This function defines your custom widget's behavior. It will be called by
+ * the widgets library to send messages to your widget. The message and widget
+ * ID are passed in, as well as two pointer-width signed parameters whose
+ * meaning varies with the message. Return 1 to indicate that you have
+ * processed the message, 0 to indicate that you have not. For any message
+ * that is not understood, return 0.
+ *
+ */
+typedef int (* XPWidgetFunc_t)(
+                         XPWidgetMessage      inMessage,
+                         XPWidgetID           inWidget,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/Widgets/XPWidgetUtils.h b/SDK/CHeaders/Widgets/XPWidgetUtils.h
new file mode 100644
index 0000000..60e4b95
--- /dev/null
+++ b/SDK/CHeaders/Widgets/XPWidgetUtils.h
@@ -0,0 +1,233 @@
+#ifndef _XPWidgetUtils_h_
+#define _XPWidgetUtils_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPWidgetUtils
+ ***************************************************************************/
+/*
+ * ## USAGE NOTES
+ * 
+ * The XPWidgetUtils library contains useful functions that make writing and
+ * using widgets less of a pain.
+ * 
+ * One set of functions are the widget behavior functions. These functions
+ * each add specific useful behaviors to widgets. They can be used in two
+ * manners:
+ * 
+ * 1. You can add a widget behavior function to a widget as a callback proc
+ *    using the XPAddWidgetCallback function. The widget will gain that
+ *    behavior. Remember that the last function you add has highest priority.
+ *    You can use this to change or augment the behavior of an existing
+ *    finished widget.
+ * 
+ * 2. You can call a widget function from inside your own widget function.
+ *    This allows you to include useful behaviors in custom-built widgets. A
+ *    number of the standard widgets get their behavior from this library. To
+ *    do this, call the behavior function from your function first. If it
+ *    returns 1, that means it handled the event and you don't need to; simply
+ *    return 1.
+ *
+ */
+
+#include "XPWidgetDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * GENERAL UTILITIES
+ ***************************************************************************/
+
+
+
+/*
+ * Convenience accessors
+ *
+ * It can be clumsy accessing the variables passed in by pointer to a struct
+ * for mouse and reshape messages; these accessors let you simply pass in the param
+ * right from the arguments of your widget proc and get back the value you want.
+ *
+ */
+#define	MOUSE_X(param) (((XPMouseState_t *) (param))->x)
+#define	MOUSE_Y(param) (((XPMouseState_t *) (param))->y)
+
+#define DELTA_X(param) (((XPWidgetGeometryChange_t *) (param))->dx)
+#define DELTA_Y(param) (((XPWidgetGeometryChange_t *) (param))->dy)
+#define DELTA_W(param) (((XPWidgetGeometryChange_t *) (param))->dwidth)
+#define DELTA_H(param) (((XPWidgetGeometryChange_t *) (param))->dheight)
+
+#define KEY_CHAR(param) (((XPKeyState_t *) (param))->key)
+#define KEY_FLAGS(param) (((XPKeyState_t *) (param))->flags)
+#define KEY_VKEY(param) (((XPKeyState_t *) (param))->vkey)
+
+#define IN_RECT(x, y, l, t, r, b)	\
+	(((x) >= (l)) && ((x) <= (r)) && ((y) >= (b)) && ((y) <= (t)))
+
+/*
+ * XPWidgetCreate_t
+ * 
+ * This structure contains all of the parameters needed to create a widget. It
+ * is used with XPUCreateWidgets to create widgets in bulk from an array. All
+ * parameters correspond to those of XPCreateWidget except for the container
+ * index.
+ * 
+ * If the container index is equal to the index of a widget in the array, the
+ * widget in the array passed to XPUCreateWidgets is used as the parent of
+ * this widget. Note that if you pass an index greater than your own position
+ * in the array, the parent you are requesting will not exist yet.
+ * 
+ * If the container index is NO_PARENT, the parent widget is specified as
+ * NULL. If the container index is PARAM_PARENT, the widget passed into
+ * XPUCreateWidgets is used.
+ *
+ */
+typedef struct {
+     int                       left;
+     int                       top;
+     int                       right;
+     int                       bottom;
+     int                       visible;
+     const char *              descriptor;
+    /* Whether this widget is a root widget                                       */
+     int                       isRoot;
+    /* The index of the widget to be contained within, or a constant              */
+     int                       containerIndex;
+     XPWidgetClass             widgetClass;
+} XPWidgetCreate_t;
+
+#define NO_PARENT            -1
+
+#define PARAM_PARENT         -2
+
+#define WIDGET_COUNT(x) ((sizeof(x) / sizeof(XPWidgetCreate_t)))
+        
+/*
+ * XPUCreateWidgets
+ * 
+ * This function creates a series of widgets from a table (see
+ * XPCreateWidget_t above). Pass in an array of widget creation structures and
+ * an array of widget IDs that will receive each widget.
+ * 
+ * Widget parents are specified by index into the created widget table,
+ * allowing you to create nested widget structures. You can create multiple
+ * widget trees in one table. Generally you should create widget trees from
+ * the top down.
+ * 
+ * You can also pass in a widget ID that will be used when the widget's parent
+ * is listed as PARAM_PARENT; this allows you to embed widgets created with
+ * XPUCreateWidgets in a widget created previously.
+ *
+ */
+WIDGET_API void       XPUCreateWidgets(
+                         const XPWidgetCreate_t * inWidgetDefs,
+                         int                  inCount,
+                         XPWidgetID           inParamParent,
+                         XPWidgetID *         ioWidgets);
+
+/*
+ * XPUMoveWidgetBy
+ * 
+ * Simply moves a widget by an amount, +x = right, +y = up, without resizing
+ * the widget.
+ *
+ */
+WIDGET_API void       XPUMoveWidgetBy(
+                         XPWidgetID           inWidget,
+                         int                  inDeltaX,
+                         int                  inDeltaY);
+
+/***************************************************************************
+ * LAYOUT MANAGERS
+ ***************************************************************************/
+/*
+ * The layout managers are widget behavior functions for handling where
+ * widgets move. Layout managers can be called from a widget function or
+ * attached to a widget later.
+ *
+ */
+
+
+/*
+ * XPUFixedLayout
+ * 
+ * This function causes the widget to maintain its children in fixed position
+ * relative to itself as it is resized. Use this on the top level 'window'
+ * widget for your window.
+ *
+ */
+WIDGET_API int        XPUFixedLayout(
+                         XPWidgetMessage      inMessage,
+                         XPWidgetID           inWidget,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2);
+
+/***************************************************************************
+ * WIDGET PROC BEHAVIORS
+ ***************************************************************************/
+/*
+ * These widget behavior functions add other useful behaviors to widgets.
+ * These functions cannot be attached to a widget; they must be called from
+ * your widget function.
+ *
+ */
+
+
+/*
+ * XPUSelectIfNeeded
+ * 
+ * This causes the widget to bring its window to the foreground if it is not
+ * already. inEatClick specifies whether clicks in the background should be
+ * consumed by bringing the window to the foreground.
+ *
+ */
+WIDGET_API int        XPUSelectIfNeeded(
+                         XPWidgetMessage      inMessage,
+                         XPWidgetID           inWidget,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2,
+                         int                  inEatClick);
+
+/*
+ * XPUDefocusKeyboard
+ * 
+ * This causes the widget to send keyboard focus back to X-Plane. This stops
+ * editing of any text fields, etc.
+ *
+ */
+WIDGET_API int        XPUDefocusKeyboard(
+                         XPWidgetMessage      inMessage,
+                         XPWidgetID           inWidget,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2,
+                         int                  inEatClick);
+
+/*
+ * XPUDragWidget
+ * 
+ * XPUDragWidget drags the widget in response to mouse clicks. Pass in not
+ * only the event, but the global coordinates of the drag region, which might
+ * be a sub-region of your widget (for example, a title bar).
+ *
+ */
+WIDGET_API int        XPUDragWidget(
+                         XPWidgetMessage      inMessage,
+                         XPWidgetID           inWidget,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/Widgets/XPWidgets.h b/SDK/CHeaders/Widgets/XPWidgets.h
new file mode 100644
index 0000000..f09885a
--- /dev/null
+++ b/SDK/CHeaders/Widgets/XPWidgets.h
@@ -0,0 +1,539 @@
+#ifndef _XPWidgets_h_
+#define _XPWidgets_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPWidgets
+ ***************************************************************************/
+/*
+ * ## THEORY OF OPERATION AND NOTES
+ * 
+ * Widgets are persistent view 'objects' for X-Plane. A widget is an object
+ * referenced by its opaque handle (widget ID) and the APIs in this file. You
+ * cannot access the widget's guts directly. Every Widget has the following
+ * intrinsic data:
+ * 
+ * - A bounding box defined in global screen coordinates with 0,0 in the
+ *   bottom left and +y = up, +x = right.
+ * - A visible box, which is the intersection of the bounding box with the
+ *   widget's parents visible box.
+ * - Zero or one parent widgets. (Always zero if the widget is a root widget.
+ * - Zero or more child widgets.
+ * - Whether the widget is a root. Root widgets are the top level plugin
+ *   windows.
+ * - Whether the widget is visible.
+ * - A text string descriptor, whose meaning varies from widget to widget.
+ * - An arbitrary set of 32 bit integral properties defined by 32-bit integral
+ *   keys. This is how specific widgets store specific data.
+ * - A list of widget callback procedures that implements the widgets
+ *   behaviors.
+ * 
+ * The Widgets library sends messages to widgets to request specific behaviors
+ * or notify the widget of things.
+ * 
+ * Widgets may have more than one callback function, in which case messages
+ * are sent to the most recently added callback function until the message is
+ * handled. Messages may also be sent to parents or children; see the
+ * XPWidgetDefs.h header file for the different widget message dispatching
+ * functions. By adding a callback function to a window you can 'subclass' its
+ * behavior.
+ * 
+ * A set of standard widgets are provided that serve common UI purposes. You
+ * can also customize or implement entirely custom widgets.
+ * 
+ * Widgets are different than other view hierarchies (most notably Win32,
+ * which they bear a striking resemblance to) in the following ways:
+ * 
+ * - Not all behavior can be patched. State that is managed by the XPWidgets
+ *   DLL and not by individual widgets cannot be customized.
+ * - All coordinates are in global screen coordinates. Coordinates are not
+ *   relative to an enclosing widget, nor are they relative to a display
+ *   window.
+ * - Widget messages are always dispatched synchronously, and there is no
+ *   concept of scheduling an update or a dirty region. Messages originate
+ *   from X-Plane as the sim cycle goes by. Since X-Plane is constantly
+ *   redrawing, so are widgets; there is no need to mark a part of a widget as
+ *   'needing redrawing' because redrawing happens frequently whether the
+ *   widget needs it or not.
+ * - Any widget may be a 'root' widget, causing it to be drawn; there is no
+ *   relationship between widget class and rootness. Root widgets are
+ *   implemented as XPLMDisplay windows.
+ *
+ */
+
+#include "XPWidgetDefs.h"
+#include "XPLMDisplay.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * WIDGET CREATION AND MANAGEMENT
+ ***************************************************************************/
+
+/*
+ * XPCreateWidget
+ * 
+ * This function creates a new widget and returns the new widget's ID to you.
+ * If the widget creation fails for some reason, it returns NULL. Widget
+ * creation will fail either if you pass a bad class ID or if there is not
+ * adequate memory.
+ * 
+ * Input Parameters:
+ * 
+ * - Top, left, bottom, and right in global screen coordinates defining the
+ *   widget's location on the screen.
+ * - inVisible is 1 if the widget should be drawn, 0 to start the widget as
+ *   hidden.
+ * - inDescriptor is a null terminated string that will become the widget's
+ *   descriptor.
+ * - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be.
+ * - inContainer is the ID of this widget's container. It must be 0 for a root
+ *   widget. For a non-root widget, pass the widget ID of the widget to place
+ *   this widget within. If this widget is not going to start inside another
+ *   widget, pass 0; this new widget will be created but will not be drawn
+ *   until it is placed inside another widget.
+ * - inClass is the class of the widget to draw. Use one of the predefined
+ *   class-IDs to create a standard widget.
+ * 
+ * A note on widget embedding: a widget is only called (and will be drawn,
+ * etc.) if it is placed within a widget that will be called. Root widgets are
+ * always called. So it is possible to have whole chains of widgets that are
+ * simply not called. You can preconstruct widget trees and then place them
+ * into root widgets later to activate them if you wish.
+ *
+ */
+WIDGET_API XPWidgetID XPCreateWidget(
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom,
+                         int                  inVisible,
+                         const char *         inDescriptor,
+                         int                  inIsRoot,
+                         XPWidgetID           inContainer,
+                         XPWidgetClass        inClass);
+
+/*
+ * XPCreateCustomWidget
+ * 
+ * This function is the same as XPCreateWidget except that instead of passing
+ * a class ID, you pass your widget callback function pointer defining the
+ * widget. Use this function to define a custom widget. All parameters are the
+ * same as XPCreateWidget, except that the widget class has been replaced with
+ * the widget function.
+ *
+ */
+WIDGET_API XPWidgetID XPCreateCustomWidget(
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom,
+                         int                  inVisible,
+                         const char *         inDescriptor,
+                         int                  inIsRoot,
+                         XPWidgetID           inContainer,
+                         XPWidgetFunc_t       inCallback);
+
+/*
+ * XPDestroyWidget
+ * 
+ * This class destroys a widget. Pass in the ID of the widget to kill. If you
+ * pass 1 for inDestroyChilren, the widget's children will be destroyed first,
+ * then this widget will be destroyed. (Furthermore, the widget's children
+ * will be destroyed with the inDestroyChildren flag set to 1, so the
+ * destruction will recurse down the widget tree.) If you pass 0 for this
+ * flag, direct child widgets will simply end up with their parent set to 0.
+ *
+ */
+WIDGET_API void       XPDestroyWidget(
+                         XPWidgetID           inWidget,
+                         int                  inDestroyChildren);
+
+/*
+ * XPSendMessageToWidget
+ * 
+ * This sends any message to a widget. You should probably not go around
+ * simulating the predefined messages that the widgets library defines for
+ * you. You may however define custom messages for your widgets and send them
+ * with this method.
+ * 
+ * This method supports several dispatching patterns; see XPDispatchMode for
+ * more info. The function returns 1 if the message was handled, 0 if it was
+ * not.
+ * 
+ * For each widget that receives the message (see the dispatching modes), each
+ * widget function from the most recently installed to the oldest one receives
+ * the message in order until it is handled.
+ *
+ */
+WIDGET_API int        XPSendMessageToWidget(
+                         XPWidgetID           inWidget,
+                         XPWidgetMessage      inMessage,
+                         XPDispatchMode       inMode,
+                         intptr_t             inParam1,
+                         intptr_t             inParam2);
+
+/***************************************************************************
+ * WIDGET POSITIONING AND VISIBILITY
+ ***************************************************************************/
+
+/*
+ * XPPlaceWidgetWithin
+ * 
+ * This function changes which container a widget resides in. You may NOT use
+ * this function on a root widget! inSubWidget is the widget that will be
+ * moved. Pass a widget ID in inContainer to make inSubWidget be a child of
+ * inContainer. It will become the last/closest widget in the container. Pass
+ * 0 to remove the widget from any container. Any call to this other than
+ * passing the widget ID of the old parent of the affected widget will cause
+ * the widget to be removed from its old parent. Placing a widget within its
+ * own parent simply makes it the last widget.
+ * 
+ * NOTE: this routine does not reposition the sub widget in global
+ * coordinates. If the container has layout management code, it will
+ * reposition the subwidget for you, otherwise you must do it with
+ * SetWidgetGeometry.
+ *
+ */
+WIDGET_API void       XPPlaceWidgetWithin(
+                         XPWidgetID           inSubWidget,
+                         XPWidgetID           inContainer);
+
+/*
+ * XPCountChildWidgets
+ * 
+ * This routine returns the number of widgets another widget contains.
+ *
+ */
+WIDGET_API int        XPCountChildWidgets(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPGetNthChildWidget
+ * 
+ * This routine returns the widget ID of a child widget by index. Indexes are
+ * 0 based, from 0 to the number of widgets in the parentone minus one,
+ * inclusive. If the index is invalid, 0 is returned.
+ *
+ */
+WIDGET_API XPWidgetID XPGetNthChildWidget(
+                         XPWidgetID           inWidget,
+                         int                  inIndex);
+
+/*
+ * XPGetParentWidget
+ * 
+ * Returns the parent of a widget, or 0 if the widget has no parent. Root
+ * widgets never have parents and therefore always return 0.
+ *
+ */
+WIDGET_API XPWidgetID XPGetParentWidget(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPShowWidget
+ * 
+ * This routine makes a widget visible if it is not already. Note that if a
+ * widget is not in a rooted widget hierarchy or one of its parents is not
+ * visible, it will still not be visible to the user.
+ *
+ */
+WIDGET_API void       XPShowWidget(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPHideWidget
+ * 
+ * Makes a widget invisible. See XPShowWidget for considerations of when a
+ * widget might not be visible despite its own visibility state.
+ *
+ */
+WIDGET_API void       XPHideWidget(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPIsWidgetVisible
+ * 
+ * This returns 1 if a widget is visible, 0 if it is not. Note that this
+ * routine takes into consideration whether a parent is invisible. Use this
+ * routine to tell if the user can see the widget.
+ *
+ */
+WIDGET_API int        XPIsWidgetVisible(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPFindRootWidget
+ * 
+ * Returns the Widget ID of the root widget that contains the passed in widget
+ * or NULL if the passed in widget is not in a rooted hierarchy.
+ *
+ */
+WIDGET_API XPWidgetID XPFindRootWidget(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPBringRootWidgetToFront
+ * 
+ * This routine makes the specified widget be in the frontmost widget
+ * hierarchy. If this widget is a root widget, its widget hierarchy comes to
+ * front, otherwise the widget's root is brought to the front. If this widget
+ * is not in an active widget hiearchy (e.g. there is no root widget at the
+ * top of the tree), this routine does nothing.
+ *
+ */
+WIDGET_API void       XPBringRootWidgetToFront(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPIsWidgetInFront
+ * 
+ * This routine returns true if this widget's hierarchy is the frontmost
+ * hierarchy. It returns false if the widget's hierarchy is not in front, or
+ * if the widget is not in a rooted hierarchy.
+ *
+ */
+WIDGET_API int        XPIsWidgetInFront(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPGetWidgetGeometry
+ * 
+ * This routine returns the bounding box of a widget in global coordinates.
+ * Pass NULL for any parameter you are not interested in.
+ *
+ */
+WIDGET_API void       XPGetWidgetGeometry(
+                         XPWidgetID           inWidget,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+
+/*
+ * XPSetWidgetGeometry
+ * 
+ * This function changes the bounding box of a widget.
+ *
+ */
+WIDGET_API void       XPSetWidgetGeometry(
+                         XPWidgetID           inWidget,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+
+/*
+ * XPGetWidgetForLocation
+ * 
+ * Given a widget and a location, this routine returns the widget ID of the
+ * child of that widget that owns that location. If inRecursive is true then
+ * this will return a child of a child of a widget as it tries to find the
+ * deepest widget at that location. If inVisibleOnly is true, then only
+ * visible widgets are considered, otherwise all widgets are considered. The
+ * widget ID passed for inContainer will be returned if the location is in
+ * that widget but not in a child widget. 0 is returned if the location is not
+ * in the container.
+ * 
+ * NOTE: if a widget's geometry extends outside its parents geometry, it will
+ * not be returned by this call for mouse locations outside the parent
+ * geometry. The parent geometry limits the child's eligibility for mouse
+ * location.
+ *
+ */
+WIDGET_API XPWidgetID XPGetWidgetForLocation(
+                         XPWidgetID           inContainer,
+                         int                  inXOffset,
+                         int                  inYOffset,
+                         int                  inRecursive,
+                         int                  inVisibleOnly);
+
+/*
+ * XPGetWidgetExposedGeometry
+ * 
+ * This routine returns the bounds of the area of a widget that is completely
+ * within its parent widgets. Since a widget's bounding box can be outside its
+ * parent, part of its area will not be eligible for mouse clicks and should
+ * not draw. Use XPGetWidgetGeometry to find out what area defines your
+ * widget's shape, but use this routine to find out what area to actually draw
+ * into. Note that the widget library does not use OpenGL clipping to keep
+ * frame rates up, although you could use it internally.
+ *
+ */
+WIDGET_API void       XPGetWidgetExposedGeometry(
+                         XPWidgetID           inWidgetID,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+
+/***************************************************************************
+ * ACCESSING WIDGET DATA
+ ***************************************************************************/
+
+/*
+ * XPSetWidgetDescriptor
+ * 
+ * Every widget has a descriptor, which is a text string. What the text string
+ * is used for varies from widget to widget; for example, a push button's text
+ * is its descriptor, a caption shows its descriptor, and a text field's
+ * descriptor is the text being edited. In other words, the usage for the text
+ * varies from widget to widget, but this API provides a universal and
+ * convenient way to get at it. While not all UI widgets need their
+ * descriptor, many do.
+ *
+ */
+WIDGET_API void       XPSetWidgetDescriptor(
+                         XPWidgetID           inWidget,
+                         const char *         inDescriptor);
+
+/*
+ * XPGetWidgetDescriptor
+ * 
+ * This routine returns the widget's descriptor. Pass in the length of the
+ * buffer you are going to receive the descriptor in. The descriptor will be
+ * null terminated for you. This routine returns the length of the actual
+ * descriptor; if you pass NULL for outDescriptor, you can get the
+ * descriptor's length without getting its text. If the length of the
+ * descriptor exceeds your buffer length, the buffer will not be null
+ * terminated (this routine has 'strncpy' semantics).
+ *
+ */
+WIDGET_API int        XPGetWidgetDescriptor(
+                         XPWidgetID           inWidget,
+                         char *               outDescriptor,
+                         int                  inMaxDescLength);
+
+/*
+ * XPGetWidgetUnderlyingWindow
+ * 
+ * Returns the window (from the XPLMDisplay API) that backs your widget
+ * window. If you have opted in to modern windows, via a call to
+ * XPLMEnableFeature("XPLM_USE_NATIVE_WIDGET_WINDOWS", 1), you can use the
+ * returned window ID for display APIs like XPLMSetWindowPositioningMode(),
+ * allowing you to pop the widget window out into a real OS window, or move it
+ * into VR.
+ *
+ */
+WIDGET_API XPLMWindowID XPGetWidgetUnderlyingWindow(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPSetWidgetProperty
+ * 
+ * This function sets a widget's property. Properties are arbitrary values
+ * associated by a widget by ID.
+ *
+ */
+WIDGET_API void       XPSetWidgetProperty(
+                         XPWidgetID           inWidget,
+                         XPWidgetPropertyID   inProperty,
+                         intptr_t             inValue);
+
+/*
+ * XPGetWidgetProperty
+ * 
+ * This routine returns the value of a widget's property, or 0 if the property
+ * is not defined. If you need to know whether the property is defined, pass a
+ * pointer to an int for inExists; the existence of that property will be
+ * returned in the int. Pass NULL for inExists if you do not need this
+ * information.
+ *
+ */
+WIDGET_API intptr_t   XPGetWidgetProperty(
+                         XPWidgetID           inWidget,
+                         XPWidgetPropertyID   inProperty,
+                         int *                inExists);              /* Can be NULL */
+
+/***************************************************************************
+ * KEYBOARD MANAGEMENT
+ ***************************************************************************/
+
+/*
+ * XPSetKeyboardFocus
+ * 
+ * Controls which widget will receive keystrokes. Pass the widget ID of the
+ * widget to get the keys. Note that if the widget does not care about
+ * keystrokes, they will go to the parent widget, and if no widget cares about
+ * them, they go to X-Plane.
+ * 
+ * If you set the keyboard focus to widget ID 0, X-Plane gets keyboard focus.
+ * 
+ * This routine returns the widget ID that ended up with keyboard focus, or 0
+ * for X-Plane.
+ * 
+ * Keyboard focus is not changed if the new widget will not accept it. For
+ * setting to X-Plane, keyboard focus is always accepted.
+ *
+ */
+WIDGET_API XPWidgetID XPSetKeyboardFocus(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPLoseKeyboardFocus
+ * 
+ * This causes the specified widget to lose focus; focus is passed to its
+ * parent, or the next parent that will accept it. This routine does nothing
+ * if this widget does not have focus.
+ *
+ */
+WIDGET_API void       XPLoseKeyboardFocus(
+                         XPWidgetID           inWidget);
+
+/*
+ * XPGetWidgetWithFocus
+ * 
+ * This routine returns the widget that has keyboard focus, or 0 if X-Plane
+ * has keyboard focus or some other plugin window that does not have widgets
+ * has focus.
+ *
+ */
+WIDGET_API XPWidgetID XPGetWidgetWithFocus(void);
+
+/***************************************************************************
+ * CREATING CUSTOM WIDGETS
+ ***************************************************************************/
+
+/*
+ * XPAddWidgetCallback
+ * 
+ * This function adds a new widget callback to a widget. This widget callback
+ * supercedes any existing ones and will receive messages first; if it does
+ * not handle messages they will go on to be handled by pre-existing widgets.
+ * 
+ * The widget function will remain on the widget for the life of the widget.
+ * The creation message will be sent to the new callback immediately with the
+ * widget ID, and the destruction message will be sent before the other widget
+ * function receives a destruction message.
+ * 
+ * This provides a way to 'subclass' an existing widget. By providing a second
+ * hook that only handles certain widget messages, you can customize or extend
+ * widget behavior.
+ *
+ */
+WIDGET_API void       XPAddWidgetCallback(
+                         XPWidgetID           inWidget,
+                         XPWidgetFunc_t       inNewCallback);
+
+/*
+ * XPGetWidgetClassFunc
+ * 
+ * Given a widget class, this function returns the callbacks that power that
+ * widget class.
+ *
+ */
+WIDGET_API XPWidgetFunc_t XPGetWidgetClassFunc(
+                         XPWidgetClass        inWidgetClass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/Wrappers/XPCBroadcaster.cpp b/SDK/CHeaders/Wrappers/XPCBroadcaster.cpp
new file mode 100755
index 0000000..5fe6218
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCBroadcaster.cpp
@@ -0,0 +1,56 @@
+#include "XPCBroadcaster.h"
+#include "XPCListener.h"
+
+XPCBroadcaster::XPCBroadcaster() :
+	mIterator(NULL)
+{
+}
+
+XPCBroadcaster::~XPCBroadcaster()
+{
+	ListenerVector::iterator iter;
+	mIterator = &iter;
+	for (iter = mListeners.begin(); iter != mListeners.end(); ++iter)
+	{
+		(*iter)->BroadcasterRemoved(this);
+	}
+}
+
+void		XPCBroadcaster::AddListener(
+				XPCListener *	inListener)
+{
+	mListeners.push_back(inListener);
+	inListener->BroadcasterAdded(this);
+}				
+
+void		XPCBroadcaster::RemoveListener(
+				XPCListener *	inListener)
+{
+	ListenerVector::iterator iter = std::find
+		(mListeners.begin(), mListeners.end(), inListener);
+	if (iter == mListeners.end())
+		return;
+		
+	if (mIterator != NULL)
+	{
+		if (*mIterator >= iter)
+			(*mIterator)--;
+	}
+	
+	mListeners.erase(iter);
+	inListener->BroadcasterRemoved(this);
+}				
+
+void		XPCBroadcaster::BroadcastMessage(
+				int			inMessage,
+				void *		inParam)
+{
+	ListenerVector::iterator iter;
+	mIterator = &iter;
+	for (iter = mListeners.begin(); iter != mListeners.end(); ++iter)
+	{
+		(*iter)->ListenToMessage(inMessage, inParam);
+	}
+	mIterator = NULL;
+}				
+
diff --git a/SDK/CHeaders/Wrappers/XPCBroadcaster.h b/SDK/CHeaders/Wrappers/XPCBroadcaster.h
new file mode 100755
index 0000000..8f34a05
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCBroadcaster.h
@@ -0,0 +1,38 @@
+#ifndef _XPCBroadcaster_h_
+#define _XPCBroadcaster_h_
+
+#include <vector>
+#include <algorithm>
+
+class	XPCListener;
+
+class	XPCBroadcaster {
+public:
+
+						XPCBroadcaster();
+	virtual				~XPCBroadcaster();
+	
+			void		AddListener(
+							XPCListener *	inListener);
+			void		RemoveListener(
+							XPCListener *	inListener);
+	
+protected:
+
+			void		BroadcastMessage(
+							int			inMessage,
+							void *		inParam=0);
+
+private:
+
+	typedef	std::vector<XPCListener *>	ListenerVector;
+	
+		ListenerVector	mListeners;
+
+	// Reentrancy support
+	
+	ListenerVector::iterator *	mIterator;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/SDK/CHeaders/Wrappers/XPCDisplay.cpp b/SDK/CHeaders/Wrappers/XPCDisplay.cpp
new file mode 100755
index 0000000..fc996ca
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCDisplay.cpp
@@ -0,0 +1,104 @@
+#include "XPCDisplay.h"
+
+XPCKeySniffer::XPCKeySniffer(int inBeforeWindows) : mBeforeWindows(inBeforeWindows)
+{
+	XPLMRegisterKeySniffer(KeySnifferCB, mBeforeWindows, reinterpret_cast<void *>(this));
+}	
+
+XPCKeySniffer::~XPCKeySniffer()
+{
+	XPLMUnregisterKeySniffer(KeySnifferCB, mBeforeWindows, reinterpret_cast<void *>(this));
+}
+
+
+int		XPCKeySniffer::KeySnifferCB(
+				char 			inCharKey, 
+				XPLMKeyFlags	inFlags,
+				char			inVirtualKey,
+				void * 			inRefCon)
+{
+	XPCKeySniffer * me = reinterpret_cast<XPCKeySniffer *>(inRefCon);
+	return me->HandleKeyStroke(inCharKey, inFlags, inVirtualKey);
+}				
+
+XPCWindow::XPCWindow(
+						int					inLeft,
+						int					inTop,
+						int					inRight,
+						int					inBottom,
+						int					inIsVisible)
+{
+	mWindow = XPLMCreateWindow(inLeft, inTop, inRight, inBottom, inIsVisible,
+							DrawCB, HandleKeyCB, MouseClickCB,
+							reinterpret_cast<void *>(this));
+}
+
+XPCWindow::~XPCWindow()
+{
+	XPLMDestroyWindow(mWindow);
+}
+
+void	XPCWindow::GetWindowGeometry(
+			int	*				outLeft,
+			int	*				outTop,
+			int	*				outRight,
+			int	*				outBottom)
+{
+	XPLMGetWindowGeometry(mWindow, outLeft, outTop, outRight, outBottom);
+}
+			
+void	XPCWindow::SetWindowGeometry(
+			int					inLeft,
+			int					inTop,
+			int					inRight,
+			int					inBottom)
+{
+	XPLMSetWindowGeometry(mWindow, inLeft, inTop, inRight, inBottom);
+}
+
+int		XPCWindow::GetWindowIsVisible(void)
+{
+	return XPLMGetWindowIsVisible(mWindow);
+}
+
+void	XPCWindow::SetWindowIsVisible(
+			int					inIsVisible)
+{
+	XPLMSetWindowIsVisible(mWindow, inIsVisible);
+}
+			
+void	XPCWindow::TakeKeyboardFocus(void)
+{
+	XPLMTakeKeyboardFocus(mWindow);
+}
+
+void	XPCWindow::BringWindowToFront(void)
+{
+	XPLMBringWindowToFront(mWindow);
+}
+
+int		XPCWindow::IsWindowInFront(void)
+{
+	return XPLMIsWindowInFront(mWindow);
+}
+		
+void	XPCWindow::DrawCB(XPLMWindowID inWindowID, void * inRefcon)
+{
+	XPCWindow * me = reinterpret_cast<XPCWindow *>(inRefcon);
+	me->DoDraw();
+}
+
+void	XPCWindow::HandleKeyCB(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char inVirtualKey, void * inRefcon, int losingFocus)
+{
+	XPCWindow * me = reinterpret_cast<XPCWindow *>(inRefcon);
+	if (losingFocus)
+		me->LoseFocus();
+	else
+		me->HandleKey(inKey, inFlags, inVirtualKey);
+}
+
+int		XPCWindow::MouseClickCB(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus inMouse, void * inRefcon)
+{
+	XPCWindow * me = reinterpret_cast<XPCWindow *>(inRefcon);
+	return me->HandleClick(x, y, inMouse);
+}
diff --git a/SDK/CHeaders/Wrappers/XPCDisplay.h b/SDK/CHeaders/Wrappers/XPCDisplay.h
new file mode 100755
index 0000000..2465928
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCDisplay.h
@@ -0,0 +1,73 @@
+#ifndef _XPCDisplay_h_
+#define _XPCDisplay_h_
+
+#include "XPLMDisplay.h"
+
+class	XPCKeySniffer {
+public:
+
+					XPCKeySniffer(int inBeforeWindows);
+	virtual			~XPCKeySniffer();
+	
+	virtual	int		HandleKeyStroke(
+							char 			inCharKey, 
+							XPLMKeyFlags	inFlags,
+							char			inVirtualKey)=0;
+
+private:
+
+		int		mBeforeWindows;
+
+	static	int		KeySnifferCB(
+							char 			inCharKey, 
+							XPLMKeyFlags	inFlags,
+							char			inVirtualKey,
+							void * 			inRefCon);
+};
+
+
+
+class	XPCWindow {
+public:
+
+					XPCWindow(
+						int					inLeft,
+						int					inTop,
+						int					inRight,
+						int					inBottom,
+						int					inIsVisible);
+	virtual			~XPCWindow();
+
+	virtual	void	DoDraw(void)=0;
+	virtual	void	HandleKey(char inKey, XPLMKeyFlags inFlags, char inVirtualKey)=0;
+	virtual	void	LoseFocus(void)=0;
+	virtual	int		HandleClick(int x, int y, XPLMMouseStatus inMouse)=0;
+	
+			void	GetWindowGeometry(
+						int	*				outLeft,
+						int	*				outTop,
+						int	*				outRight,
+						int	*				outBottom);
+			void	SetWindowGeometry(
+						int					inLeft,
+						int					inTop,
+						int					inRight,
+						int					inBottom);
+			int		GetWindowIsVisible(void);
+			void	SetWindowIsVisible(
+						int					inIsVisible);
+			void	TakeKeyboardFocus(void);
+			void	BringWindowToFront(void);
+			int		IsWindowInFront(void);
+		
+private:
+
+		XPLMWindowID	mWindow;
+
+	static	void	DrawCB(XPLMWindowID inWindowID, void * inRefcon);
+	static	void	HandleKeyCB(XPLMWindowID inWindowID, char inKey, XPLMKeyFlags inFlags, char inVirtualKey, void * inRefcon, int losingFocus);
+	static	int		MouseClickCB(XPLMWindowID inWindowID, int x, int y, XPLMMouseStatus inMouse, void * inRefcon);
+
+};
+
+#endif
\ No newline at end of file
diff --git a/SDK/CHeaders/Wrappers/XPCListener.cpp b/SDK/CHeaders/Wrappers/XPCListener.cpp
new file mode 100755
index 0000000..b4c77aa
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCListener.cpp
@@ -0,0 +1,27 @@
+#include "XPCListener.h"
+#include "XPCBroadcaster.h"
+
+XPCListener::XPCListener()
+{
+}
+
+XPCListener::~XPCListener()
+{
+	while (!mBroadcasters.empty())
+		mBroadcasters.front()->RemoveListener(this);
+}
+	
+void		XPCListener::BroadcasterAdded(
+							XPCBroadcaster *	inBroadcaster)
+{
+	mBroadcasters.push_back(inBroadcaster);
+}							
+
+void		XPCListener::BroadcasterRemoved(
+							XPCBroadcaster *	inBroadcaster)
+{
+	BroadcastVector::iterator iter = std::find(mBroadcasters.begin(),
+		mBroadcasters.end(), inBroadcaster);
+	if (iter != mBroadcasters.end())
+		mBroadcasters.erase(iter);
+}							
diff --git a/SDK/CHeaders/Wrappers/XPCListener.h b/SDK/CHeaders/Wrappers/XPCListener.h
new file mode 100755
index 0000000..dbdd2a0
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCListener.h
@@ -0,0 +1,36 @@
+#ifndef _XPCListener_h_
+#define _XPCListener_h_
+
+#include <vector>
+#include <algorithm>
+
+class	XPCBroadcaster;
+
+
+class	XPCListener {
+public:
+
+						XPCListener();
+	virtual				~XPCListener();
+	
+	virtual	void		ListenToMessage(
+							int				inMessage,
+							void *			inParam)=0;
+							
+private:
+
+	typedef	std::vector<XPCBroadcaster *>	BroadcastVector;
+	
+	BroadcastVector	mBroadcasters;
+
+	friend	class	XPCBroadcaster;
+	
+			void		BroadcasterAdded(
+							XPCBroadcaster *	inBroadcaster);
+
+			void		BroadcasterRemoved(
+							XPCBroadcaster *	inBroadcaster);
+			
+};			
+
+#endif
\ No newline at end of file
diff --git a/SDK/CHeaders/Wrappers/XPCProcessing.cpp b/SDK/CHeaders/Wrappers/XPCProcessing.cpp
new file mode 100755
index 0000000..352c05f
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCProcessing.cpp
@@ -0,0 +1,52 @@
+#include "XPCProcessing.h"
+#include "XPLMUtilities.h"
+
+XPCProcess::XPCProcess() :
+	mInCallback(false),
+	mCallbackTime(0)
+{
+	XPLMRegisterFlightLoopCallback(FlightLoopCB, 0, reinterpret_cast<void *>(this));
+}
+
+XPCProcess::~XPCProcess()
+{
+	XPLMUnregisterFlightLoopCallback(FlightLoopCB, reinterpret_cast<void *>(this));
+}
+	
+void		XPCProcess::StartProcessTime(float	inSeconds)
+{
+	mCallbackTime = inSeconds;
+	if (!mInCallback)
+		XPLMSetFlightLoopCallbackInterval(
+			FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast<void *>(this));
+}
+
+void		XPCProcess::StartProcessCycles(int	inCycles)
+{
+	mCallbackTime = -inCycles;
+	if (!mInCallback)
+		XPLMSetFlightLoopCallbackInterval(
+			FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast<void *>(this));
+}
+
+void		XPCProcess::StopProcess(void)
+{
+	mCallbackTime = 0;
+	if (!mInCallback)
+		XPLMSetFlightLoopCallbackInterval(
+			FlightLoopCB, mCallbackTime, 1/*relative to now*/, reinterpret_cast<void *>(this));
+}
+
+
+float	XPCProcess::FlightLoopCB(
+						float 				inElapsedSinceLastCall, 
+						float				inElapsedTimeSinceLastFlightLoop,
+						int 				inCounter, 
+						void * 				inRefcon)
+{
+	XPCProcess * me = reinterpret_cast<XPCProcess *>(inRefcon);
+	me->mInCallback = true;
+	me->DoProcessing(inElapsedSinceLastCall, inElapsedTimeSinceLastFlightLoop, inCounter);
+	me->mInCallback = false;
+	return me->mCallbackTime;
+}
\ No newline at end of file
diff --git a/SDK/CHeaders/Wrappers/XPCProcessing.h b/SDK/CHeaders/Wrappers/XPCProcessing.h
new file mode 100755
index 0000000..cd735e5
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCProcessing.h
@@ -0,0 +1,37 @@
+#ifndef _XPCProcessing_h_
+#define _XPCProcessing_h_
+
+#include "XPLMProcessing.h"
+
+class	XPCProcess {
+public:
+
+						XPCProcess();
+	virtual				~XPCProcess();
+	
+			void		StartProcessTime(float	inSeconds);
+			void		StartProcessCycles(int	inCycles);
+			void		StopProcess(void);
+
+	virtual	void		DoProcessing(
+							float 				inElapsedSinceLastCall, 
+							float				inElapsedTimeSinceLastFlightLoop,
+							int 				inCounter)=0;
+
+private:
+
+	static	float	FlightLoopCB(
+							float 				inElapsedSinceLastCall, 
+							float				inElapsedTimeSinceLastFlightLoop,
+							int 				inCounter, 
+							void * 				inRefcon);
+						
+		bool		mInCallback;
+		float		mCallbackTime;
+		
+	XPCProcess(const XPCProcess&);
+	XPCProcess& operator=(const XPCProcess&);
+
+};
+
+#endif
diff --git a/SDK/CHeaders/Wrappers/XPCWidget.cpp b/SDK/CHeaders/Wrappers/XPCWidget.cpp
new file mode 100755
index 0000000..8ef8aa3
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCWidget.cpp
@@ -0,0 +1,123 @@
+#include "XPCWidget.h"
+
+XPCWidget::XPCWidget(
+		int						inLeft,
+		int						inTop,
+		int						inRight,
+		int						inBottom,
+		bool					inVisible,
+		const char *			inDescriptor,
+		bool					inIsRoot,
+		XPWidgetID				inParent,
+		XPWidgetClass			inClass) :
+	mWidget(NULL),
+	mOwnsChildren(false),
+	mOwnsWidget(true)
+{
+	mWidget = XPCreateWidget(
+		inLeft, inTop, inRight, inBottom,
+		inVisible ? 1 : 0,
+		inDescriptor,
+		inIsRoot ? 1 : 0,
+		inIsRoot ? NULL : inParent,
+		inClass);
+
+	XPSetWidgetProperty(mWidget, xpProperty_Object, reinterpret_cast<intptr_t>(this));		
+	XPAddWidgetCallback(mWidget, WidgetCallback);
+}								
+						
+XPCWidget::XPCWidget(
+	XPWidgetID				inWidget,
+	bool					inOwnsWidget) :
+	mWidget(inWidget),
+	mOwnsChildren(false),
+	mOwnsWidget(inOwnsWidget)
+{
+	XPSetWidgetProperty(mWidget, xpProperty_Object, reinterpret_cast<intptr_t>(this));		
+	XPAddWidgetCallback(mWidget, WidgetCallback);
+}
+
+XPCWidget::~XPCWidget()
+{
+	if (mOwnsWidget)
+		XPDestroyWidget(mWidget, mOwnsChildren ? 1 : 0);
+}
+	
+void		XPCWidget::SetOwnsWidget(
+					bool 					inOwnsWidget)
+{
+	mOwnsWidget = inOwnsWidget;
+}
+
+void		XPCWidget::SetOwnsChildren(
+					bool 					inOwnsChildren)
+{
+	mOwnsChildren = inOwnsChildren;
+}					
+
+XPCWidget::operator XPWidgetID () const
+{
+	return mWidget;
+}
+
+XPWidgetID XPCWidget::Get(void) const
+{
+	return mWidget;
+}
+
+void		XPCWidget::AddAttachment(
+								XPCWidgetAttachment * 	inAttachment, 
+								bool 					inOwnsAttachment,
+								bool					inPrefilter)
+{
+	if (inPrefilter)
+	{
+		mAttachments.insert(mAttachments.begin(), AttachmentInfo(inAttachment, inOwnsAttachment));
+	} else {
+		mAttachments.push_back(AttachmentInfo(inAttachment, inOwnsAttachment));
+	}
+}								
+
+void		XPCWidget::RemoveAttachment(
+								XPCWidgetAttachment * 	inAttachment)
+{
+	for (AttachmentVector::iterator iter = mAttachments.begin();
+			iter != mAttachments.end(); ++iter)
+	{
+		if (iter->first == inAttachment)
+		{
+			mAttachments.erase(iter);
+			return;
+		}
+	}
+}								
+
+int			XPCWidget::HandleWidgetMessage(
+								XPWidgetMessage			inMessage,
+								XPWidgetID				inWidget,
+								intptr_t				inParam1,
+								intptr_t				inParam2)
+{
+	return 0;
+}								
+		
+int			XPCWidget::WidgetCallback(
+								XPWidgetMessage			inMessage,
+								XPWidgetID				inWidget,
+								intptr_t				inParam1,
+								intptr_t				inParam2)
+{
+	XPCWidget * me = reinterpret_cast<XPCWidget *>(XPGetWidgetProperty(inWidget, xpProperty_Object, NULL));
+	if (me == NULL)
+		return 0;
+	
+	for (AttachmentVector::iterator iter = me->mAttachments.begin(); iter != 
+		me->mAttachments.end(); ++iter)
+	{
+		int result = iter->first->HandleWidgetMessage(me, inMessage, inWidget, inParam1, inParam2);
+		if (result != 0)
+			return result;
+	}
+
+	return me->HandleWidgetMessage(inMessage, inWidget, inParam1, inParam2);
+}								
diff --git a/SDK/CHeaders/Wrappers/XPCWidget.h b/SDK/CHeaders/Wrappers/XPCWidget.h
new file mode 100755
index 0000000..788b56a
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCWidget.h
@@ -0,0 +1,84 @@
+#ifndef _XPCWidget_h_
+#define _XPCWidget_h_
+
+#include <vector>
+#include <algorithm>
+#include "XPWidgets.h"
+
+class	XPCWidget;
+
+class	XPCWidgetAttachment {
+public:
+
+	virtual	int			HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)=0;
+								
+};
+
+class	XPCWidget {
+public:
+
+						XPCWidget(
+								int						inLeft,
+								int						inTop,
+								int						inRight,
+								int						inBottom,
+								bool					inVisible,
+								const char *			inDescriptor,
+								bool					inIsRoot,
+								XPWidgetID				inParent,
+								XPWidgetClass			inClass);
+						XPCWidget(
+								XPWidgetID				inWidget,
+								bool					inOwnsWidget);
+	virtual				~XPCWidget();
+	
+			void		SetOwnsWidget(
+								bool 					inOwnsWidget);
+			void		SetOwnsChildren(
+								bool 					inOwnsChildren);
+
+			operator XPWidgetID () const;
+			
+			XPWidgetID	Get(void) const;
+
+			void		AddAttachment(
+								XPCWidgetAttachment * 	inAttachment, 
+								bool 					inOwnsAttachment,
+								bool					inPrefilter);
+			void		RemoveAttachment(
+								XPCWidgetAttachment * 	inAttachment);
+
+	virtual	int			HandleWidgetMessage(
+								XPWidgetMessage			inMessage,
+								XPWidgetID				inWidget,
+								intptr_t				inParam1,
+								intptr_t				inParam2);
+		
+private:
+
+	static	int			WidgetCallback(
+								XPWidgetMessage			inMessage,
+								XPWidgetID				inWidget,
+								intptr_t				inParam1,
+								intptr_t				inParam2);
+		
+	typedef	std::pair<XPCWidgetAttachment *, bool>	AttachmentInfo;
+	typedef	std::vector<AttachmentInfo>				AttachmentVector;
+		
+		AttachmentVector		mAttachments;
+		XPWidgetID				mWidget;
+		bool					mOwnsChildren;
+		bool					mOwnsWidget;
+	
+	XPCWidget();							
+	XPCWidget(const XPCWidget&);
+	XPCWidget& operator=(const XPCWidget&);
+
+};
+
+#endif
\ No newline at end of file
diff --git a/SDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp b/SDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp
new file mode 100755
index 0000000..d87f105
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp
@@ -0,0 +1,267 @@
+#include "XPCWidgetAttachments.h"
+#include "XPStandardWidgets.h"
+#include "XPWidgetUtils.h"
+
+static	void	XPCGetOrderedSubWidgets(
+							XPWidgetID						inWidget,
+							std::vector<XPWidgetID>&		outChildren);					
+
+XPCKeyFilterAttachment::XPCKeyFilterAttachment(
+								const char *	inValidKeys,
+								const char *	outValidKeys) :
+	mInput(inValidKeys),
+	mOutput(outValidKeys)
+{
+}								
+								
+XPCKeyFilterAttachment::~XPCKeyFilterAttachment()
+{
+}
+
+int		XPCKeyFilterAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if (inMessage == xpMsg_KeyPress)
+	{
+		char&	theKey = KEY_CHAR(inParam1);
+		std::string::size_type pos = mInput.find(theKey);
+		if (pos == std::string::npos)
+			return 1;	// Not found; eat the key!
+		else {
+			theKey = mOutput[pos];
+			return 0;
+		}	// Let it live.
+	}
+	return 0;
+}								
+
+
+XPCKeyMessageAttachment::XPCKeyMessageAttachment(
+								char			inKey,
+								int				inMessage,
+								void *			inParam,
+								bool			inConsume,
+								bool			inVkey,
+								XPCListener *	inListener) :
+	mKey(inKey), mMsg(inMessage), mParam(inParam), mConsume(inConsume),
+	mVkey(inVkey)
+{
+	if (inListener != NULL)
+		this->AddListener(inListener);
+}	
+
+XPCKeyMessageAttachment::~XPCKeyMessageAttachment()
+{
+}
+									
+int		XPCKeyMessageAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if (inMessage == xpMsg_KeyPress)
+	{
+		char theKey = mVkey ? KEY_VKEY(inParam1) : KEY_CHAR(inParam1);
+		if (theKey != mKey)
+			return 0;
+		if (!(KEY_FLAGS(inParam1) & xplm_DownFlag))
+			return 0;
+		
+		BroadcastMessage(mMsg, mParam);
+		return mConsume ? 1 : 0;
+	}
+	return 0;
+}								
+
+XPCPushButtonMessageAttachment::XPCPushButtonMessageAttachment(
+									XPWidgetID		inWidget,
+									int				inMessage,
+									void *			inParam,
+									XPCListener *	inListener) :
+	mMsg(inMessage), mParam(inParam), mWidget(inWidget)
+{
+	if (inListener != NULL)
+		this->AddListener(inListener);
+}
+
+XPCPushButtonMessageAttachment::~XPCPushButtonMessageAttachment()
+{
+}
+
+int		XPCPushButtonMessageAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if ((inMessage == xpMsg_PushButtonPressed) && ((XPWidgetID) inParam1 == mWidget))
+	{
+		BroadcastMessage(mMsg, mParam);
+		return 1;
+	}
+
+	if ((inMessage == xpMsg_ButtonStateChanged) && ((XPWidgetID) inParam1 == mWidget))
+	{
+		BroadcastMessage(mMsg, mParam);
+		return 1;
+	}
+	return 0;	
+}					
+
+XPCSliderMessageAttachment::XPCSliderMessageAttachment(
+									XPWidgetID		inWidget,
+									int				inMessage,
+									void *			inParam,
+									XPCListener *	inListener) :
+	mMsg(inMessage), mParam(inParam), mWidget(inWidget)
+{
+	if (inListener != NULL)
+		this->AddListener(inListener);
+}
+
+XPCSliderMessageAttachment::~XPCSliderMessageAttachment()
+{
+}
+
+int		XPCSliderMessageAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if ((inMessage == xpMsg_ScrollBarSliderPositionChanged) && ((XPWidgetID) inParam1 == mWidget))
+	{
+		BroadcastMessage(mMsg, mParam);
+		return 1;
+	}
+
+	return 0;	
+}									
+
+
+XPCCloseButtonMessageAttachment::XPCCloseButtonMessageAttachment(
+									XPWidgetID		inWidget,
+									int				inMessage,
+									void *			inParam,
+									XPCListener *	inListener) :
+	mMsg(inMessage), mParam(inParam), mWidget(inWidget)
+{
+	if (inListener != NULL)
+		this->AddListener(inListener);
+}
+
+XPCCloseButtonMessageAttachment::~XPCCloseButtonMessageAttachment()
+{
+}
+
+int		XPCCloseButtonMessageAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if ((inMessage == xpMessage_CloseButtonPushed) && ((XPWidgetID) inParam1 == mWidget))
+	{
+		BroadcastMessage(mMsg, mParam);
+		return 1;
+	}
+
+	return 0;	
+}									
+
+XPCTabGroupAttachment::XPCTabGroupAttachment()
+{
+}
+
+XPCTabGroupAttachment::~XPCTabGroupAttachment()
+{
+}
+
+int		XPCTabGroupAttachment::HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2)
+{
+	if ((inMessage == xpMsg_KeyPress) && (KEY_CHAR(inParam1) == XPLM_KEY_TAB) &&
+		((KEY_FLAGS(inParam1) & xplm_UpFlag) == 0))
+	{
+		bool backwards = (KEY_FLAGS(inParam1) & xplm_ShiftFlag) != 0;
+		std::vector<XPWidgetID>	widgets;
+		XPCGetOrderedSubWidgets(inWidget, widgets);
+		int	n, index = 0;
+		XPWidgetID	focusWidget = XPGetWidgetWithFocus();
+		std::vector<XPWidgetID>::iterator iter = std::find(widgets.begin(), widgets.end(), focusWidget);
+		if (iter != widgets.end())
+		{
+			index = std::distance(widgets.begin(), iter);
+			if (backwards)
+				index--;
+			else
+				index++;
+			if (index < 0)
+				index = widgets.size() - 1;
+			if (index >= widgets.size())
+				index = 0;
+		}
+		
+		if (backwards)
+		{
+			for (n = index; n >= 0; --n)
+			{
+				if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL))
+				if (XPSetKeyboardFocus(widgets[n]) != NULL)
+					return 1;
+			}
+			for (n = widgets.size() - 1; n > index; --n)
+			{
+				if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL))
+				if (XPSetKeyboardFocus(widgets[n]) != NULL)
+					return 1;
+			}				
+		} else {
+			for (n = index; n < widgets.size(); ++n)
+			{
+				if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL))
+				if (XPSetKeyboardFocus(widgets[n]) != NULL)
+					return 1;
+			}
+			for (n = 0; n < index; ++n)
+			{
+				if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL))
+				if (XPSetKeyboardFocus(widgets[n]) != NULL)
+					return 1;
+			}				
+		}
+	} 
+	return 0;
+}								
+
+
+
+static	void	XPCGetOrderedSubWidgets(
+							XPWidgetID						inWidget,
+							std::vector<XPWidgetID>&		outChildren)
+{
+	outChildren.clear();
+	int	count = XPCountChildWidgets(inWidget);
+	for (int n = 0; n < count; ++n)
+	{
+		XPWidgetID	child = XPGetNthChildWidget(inWidget, n);
+		outChildren.push_back(child);
+		std::vector<XPWidgetID>	grandChildren;
+		XPCGetOrderedSubWidgets(child, grandChildren);
+		
+		outChildren.insert(outChildren.end(), grandChildren.begin(), grandChildren.end());
+	}
+}							
diff --git a/SDK/CHeaders/Wrappers/XPCWidgetAttachments.h b/SDK/CHeaders/Wrappers/XPCWidgetAttachments.h
new file mode 100755
index 0000000..91fb587
--- /dev/null
+++ b/SDK/CHeaders/Wrappers/XPCWidgetAttachments.h
@@ -0,0 +1,146 @@
+#ifndef _XPCWidgetAttachments_h_
+#define _XPCWidgetAttachments_h_
+
+#include <string>
+
+#include "XPCWidget.h"
+#include "XPCBroadcaster.h"
+
+class	XPCKeyFilterAttachment : public XPCWidgetAttachment {
+public:
+
+					XPCKeyFilterAttachment(
+								const char *	inValidKeys,
+								const char *	outValidKeys);
+	virtual			~XPCKeyFilterAttachment();
+
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+private:
+
+	std::string		mInput;
+	std::string		mOutput;
+
+};
+
+
+class	XPCKeyMessageAttachment : public XPCWidgetAttachment, public XPCBroadcaster {
+public:
+
+					XPCKeyMessageAttachment(
+								char			inKey,
+								int				inMessage,
+								void *			inParam,
+								bool			inConsume,
+								bool			inVkey,
+								XPCListener *	inListener);
+	virtual			~XPCKeyMessageAttachment();
+									
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+private:
+
+		char	mKey;
+		bool	mVkey;
+		int		mMsg;
+		void *	mParam;
+		bool	mConsume;
+	
+};
+
+class	XPCPushButtonMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster {
+public:
+
+					XPCPushButtonMessageAttachment(
+								XPWidgetID		inWidget,
+								int				inMessage,
+								void *			inParam,
+								XPCListener *	inListener);
+	virtual			~XPCPushButtonMessageAttachment();
+
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+private:
+		XPWidgetID	mWidget;
+		int			mMsg;
+		void *		mParam;
+};
+
+class	XPCSliderMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster {
+public:
+
+					XPCSliderMessageAttachment(
+								XPWidgetID		inWidget,
+								int				inMessage,
+								void *			inParam,
+								XPCListener *	inListener);
+	virtual			~XPCSliderMessageAttachment();
+
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+private:
+		XPWidgetID	mWidget;
+		int			mMsg;
+		void *		mParam;
+};
+
+
+class	XPCCloseButtonMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster {
+public:
+
+					XPCCloseButtonMessageAttachment(
+								XPWidgetID		inWidget,
+								int				inMessage,
+								void *			inParam,
+								XPCListener *	inListener);
+	virtual			~XPCCloseButtonMessageAttachment();
+
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+private:
+		XPWidgetID	mWidget;
+		int			mMsg;
+		void *		mParam;
+};
+
+class	XPCTabGroupAttachment : public XPCWidgetAttachment {
+public:
+
+					XPCTabGroupAttachment();
+	virtual			~XPCTabGroupAttachment();
+
+	virtual	int		HandleWidgetMessage(
+								XPCWidget *		inObject,
+								XPWidgetMessage	inMessage,
+								XPWidgetID		inWidget,
+								intptr_t		inParam1,
+								intptr_t		inParam2);
+
+};
+
+#endif
\ No newline at end of file
diff --git a/SDK/CHeaders/XPLM/XPLMCamera.h b/SDK/CHeaders/XPLM/XPLMCamera.h
new file mode 100644
index 0000000..8b88d28
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMCamera.h
@@ -0,0 +1,167 @@
+#ifndef _XPLMCamera_h_
+#define _XPLMCamera_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMCamera
+ ***************************************************************************/
+/*
+ * The XPLMCamera APIs allow plug-ins to control the camera angle in X-Plane.
+ * This has a number of applications, including but not limited to:
+ * 
+ * - Creating new views (including dynamic/user-controllable views) for the
+ *   user.
+ * - Creating applications that use X-Plane as a renderer of scenery,
+ *   aircrafts, or both.
+ * 
+ * The camera is controlled via six parameters: a location in OpenGL
+ * coordinates and pitch, roll and yaw, similar to an airplane's position.
+ * OpenGL coordinate info is described in detail in the XPLMGraphics
+ * documentation; generally you should use the XPLMGraphics routines to
+ * convert from world to local coordinates. The camera's orientation starts
+ * facing level with the ground directly up the negative-Z axis (approximately
+ * north) with the horizon horizontal. It is then rotated clockwise for yaw,
+ * pitched up for positive pitch, and rolled clockwise around the vector it is
+ * looking along for roll.
+ * 
+ * You control the camera either either until the user selects a new view or
+ * permanently (the latter being similar to how UDP camera control works). You
+ * control the camera by registering a callback per frame from which you
+ * calculate the new camera positions. This guarantees smooth camera motion.
+ * 
+ * Use the XPLMDataAccess APIs to get information like the position of the
+ * aircraft, etc. for complex camera positioning.
+ * 
+ * Note: if your goal is to move the virtual pilot in the cockpit, this API is
+ * not needed; simply update the datarefs for the pilot's head position.
+ * 
+ * For custom exterior cameras, set the camera's mode to an external view
+ * first to get correct sound and 2-d panel behavior.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * CAMERA CONTROL
+ ***************************************************************************/
+
+/*
+ * XPLMCameraControlDuration
+ * 
+ * This enumeration states how long you want to retain control of the camera.
+ * You can retain it indefinitely or until the user selects a new view.
+ *
+ */
+enum {
+    /* Control the camera until the user picks a new view.                        */
+    xplm_ControlCameraUntilViewChanges       = 1,
+
+    /* Control the camera until your plugin is disabled or another plugin forcibly*
+     * takes control.                                                             */
+    xplm_ControlCameraForever                = 2,
+
+
+};
+typedef int XPLMCameraControlDuration;
+
+/*
+ * XPLMCameraPosition_t
+ * 
+ * This structure contains a full specification of the camera. X, Y, and Z are
+ * the camera's position in OpenGL coordinates; pitch, roll, and yaw are
+ * rotations from a camera facing flat north in degrees. Positive pitch means
+ * nose up, positive roll means roll right, and positive yaw means yaw right,
+ * all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0
+ * magnifying by 2x (objects appear larger).
+ *
+ */
+typedef struct {
+     float                     x;
+     float                     y;
+     float                     z;
+     float                     pitch;
+     float                     heading;
+     float                     roll;
+     float                     zoom;
+} XPLMCameraPosition_t;
+
+/*
+ * XPLMCameraControl_f
+ * 
+ * You use an XPLMCameraControl function to provide continuous control over
+ * the camera. You are passed a structure in which to put the new camera
+ * position; modify it and return 1 to reposition the camera. Return 0 to
+ * surrender control of the camera; camera control will be handled by X-Plane
+ * on this draw loop. The contents of the structure as you are called are
+ * undefined.
+ * 
+ * If X-Plane is taking camera control away from you, this function will be
+ * called with inIsLosingControl set to 1 and ioCameraPosition NULL.
+ *
+ */
+typedef int (* XPLMCameraControl_f)(
+                         XPLMCameraPosition_t * outCameraPosition,      /* Can be NULL */
+                         int                  inIsLosingControl,
+                         void *               inRefcon);
+
+/*
+ * XPLMControlCamera
+ * 
+ * This function repositions the camera on the next drawing cycle. You must
+ * pass a non-null control function. Specify in inHowLong how long you'd like
+ * control (indefinitely or until a new view mode is set by the user).
+ *
+ */
+XPLM_API void       XPLMControlCamera(
+                         XPLMCameraControlDuration inHowLong,
+                         XPLMCameraControl_f  inControlFunc,
+                         void *               inRefcon);
+
+/*
+ * XPLMDontControlCamera
+ * 
+ * This function stops you from controlling the camera. If you have a camera
+ * control function, it will not be called with an inIsLosingControl flag.
+ * X-Plane will control the camera on the next cycle.
+ * 
+ * For maximum compatibility you should not use this routine unless you are in
+ * posession of the camera.
+ *
+ */
+XPLM_API void       XPLMDontControlCamera(void);
+
+/*
+ * XPLMIsCameraBeingControlled
+ * 
+ * This routine returns 1 if the camera is being controlled, zero if it is
+ * not. If it is and you pass in a pointer to a camera control duration, the
+ * current control duration will be returned.
+ *
+ */
+XPLM_API int        XPLMIsCameraBeingControlled(
+                         XPLMCameraControlDuration * outCameraControlDuration);    /* Can be NULL */
+
+/*
+ * XPLMReadCameraPosition
+ * 
+ * This function reads the current camera position.
+ *
+ */
+XPLM_API void       XPLMReadCameraPosition(
+                         XPLMCameraPosition_t * outCameraPosition);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMDataAccess.h b/SDK/CHeaders/XPLM/XPLMDataAccess.h
new file mode 100644
index 0000000..22c28ee
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMDataAccess.h
@@ -0,0 +1,798 @@
+#ifndef _XPLMDataAccess_h_
+#define _XPLMDataAccess_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMDataAccess
+ ***************************************************************************/
+/*
+ * The data access API gives you a generic, flexible, high performance way to
+ * read and write data to and from X-Plane and other plug-ins. For example,
+ * this API allows you to read and set the nav radios, get the plane location,
+ * determine the current effective graphics frame rate, etc.
+ * 
+ * The data access APIs are the way that you read and write data from the sim
+ * as well as other plugins.
+ * 
+ * The API works using opaque data references. A data reference is a source of
+ * data; you do not know where it comes from, but once you have it you can
+ * read the data quickly and possibly write it.
+ * 
+ * Dataref Lookup
+ * --------------
+ * 
+ * Data references are identified by verbose, permanent string names; by
+ * convention these names use path separators to form a hierarchy of datarefs,
+ * e.g. (sim/cockpit/radios/nav1_freq_hz). The actual opaque numeric value of
+ * the data reference, as returned by the XPLM API, is implementation defined
+ * and changes each time X-Plane is launched; therefore you need to look up
+ * the dataref by path every time your plugin runs.
+ * 
+ * The task of looking up a data reference is relatively expensive; look up
+ * your data references once based on the verbose path strings, and save the
+ * opaque data reference value for the duration of your plugin's operation.
+ * Reading and writing data references is relatively fast (the cost is
+ * equivalent to two function calls through function pointers).
+ * 
+ * X-Plane publishes many thousands of datarefs; a complete list may be found
+ * in the reference section of the SDK online documentation (from the SDK home
+ * page, choose Documentation) and the Resources/plugins/DataRefs.txt file.
+ * 
+ * Dataref Types
+ * -------------
+ * 
+ * A note on typing: you must know the correct data type to read and write.
+ * APIs are provided for reading and writing data in a number of ways. You can
+ * also double check the data type for a dataref. Automatic type conversion is
+ * not done for you.
+ * 
+ * Dataref types are a set, e.g. a dataref can be more than one type.  When
+ * this happens, you can choose which API you want to use to read.  For
+ * example, it is not uncommon for a dataref to be available both as float and
+ * double.  This means you can use either XPLMGetDatad or XPLMGetDataf to read
+ * it.
+ * 
+ * Creating New Datarefs
+ * ---------------------
+ * 
+ * X-Plane provides datarefs that come with the sim, but plugins can also
+ * create their own datarefs.  A plugin creates a dataref by registering
+ * function callbacks to read and write the dataref.  The XPLM will call your
+ * plugin each time some other plugin (or X-Plane) tries to read or write the
+ * dataref.  You must provide a read (and optional write) callback for each
+ * data type you support.
+ * 
+ * A note for plugins sharing data with other plugins: the load order of
+ * plugins is not guaranteed. To make sure that every plugin publishing data
+ * has published their data references before other plugins try to subscribe,
+ * publish your data references in your start routine but resolve others'
+ * datarefs the first time your 'enable' routine is called, or the first time
+ * they are needed in code.
+ * 
+ * When a plugin that created a dataref is unloaded, it becomes "orphaned". 
+ * The dataref handle continues to be usable, but the dataref is not writable,
+ * and reading it will always return 0 (or 0 items for arrays).  If the plugin
+ * is reloaded and re-registers the dataref, the handle becomes un-orphaned
+ * and works again.
+ * 
+ * Introspection: Finding All Datarefs
+ * -----------------------------------
+ * 
+ * In the XPLM400 API, it is possible for a plugin to iterate the entire set
+ * of datarefs. This functionality is meant only for "tool" add-ons, like
+ * dataref browsers; normally all add-ons  should find the dataref they want
+ * by name.
+ * 
+ * Because datarefs are never destroyed during a run of the simulator (they
+ * are orphaned when their providing plugin goes away until a new one
+ * re-registers the dataref), the set of  datarefs for a given run of X-Plane
+ * can be enumerated by index. A plugin that wants to find all new datarefs
+ * can use XPLMCountDataRefs to find the number of datarefs and iterate only 
+ * the ones with higher index numbers than the last iteration.
+ * 
+ * Plugins can also receive notifications when datarefs are registered; see
+ * the XPLMPlugin feature-enable API for more details.    
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * READING AND WRITING DATA
+ ***************************************************************************/
+/*
+ * These routines allow you to access data from within X-Plane and sometimes
+ * modify it.
+ *
+ */
+
+
+/*
+ * XPLMDataRef
+ * 
+ * A dataref is an opaque handle to data provided by the simulator or another
+ * plugin. It uniquely identifies one variable (or array of variables) over
+ * the lifetime of your plugin. You never hard code these values; you always
+ * get them from XPLMFindDataRef.
+ *
+ */
+typedef void * XPLMDataRef;
+
+/*
+ * XPLMDataTypeID
+ * 
+ * This is an enumeration that defines the type of the data behind a data
+ * reference. This allows you to sanity check that the data type matches what
+ * you expect. But for the most part, you will know the type of data you are
+ * expecting from the online documentation.
+ * 
+ * Data types each take a bit field; it is legal to have a single dataref be
+ * more than one type of data.  Whe this happens, you can pick any matching
+ * get/set API.
+ *
+ */
+enum {
+    /* Data of a type the current XPLM doesn't do.                                */
+    xplmType_Unknown                         = 0,
+
+    /* A single 4-byte integer, native endian.                                    */
+    xplmType_Int                             = 1,
+
+    /* A single 4-byte float, native endian.                                      */
+    xplmType_Float                           = 2,
+
+    /* A single 8-byte double, native endian.                                     */
+    xplmType_Double                          = 4,
+
+    /* An array of 4-byte floats, native endian.                                  */
+    xplmType_FloatArray                      = 8,
+
+    /* An array of 4-byte integers, native endian.                                */
+    xplmType_IntArray                        = 16,
+
+    /* A variable block of data.                                                  */
+    xplmType_Data                            = 32,
+
+
+};
+typedef int XPLMDataTypeID;
+
+#if defined(XPLM400)
+/*
+ * XPLMCountDataRefs
+ * 
+ * Returns the total number of datarefs that have been registered in X-Plane.
+ *
+ */
+XPLM_API int        XPLMCountDataRefs(void);
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/*
+ * XPLMGetDataRefsByIndex
+ * 
+ * Given an offset and count, this function will return an array of
+ * XPLMDataRefs in that range.  The offset/count idiom is useful for things
+ * like pagination.
+ *
+ */
+XPLM_API void       XPLMGetDataRefsByIndex(
+                         int                  offset,
+                         int                  count,
+                         XPLMDataRef *        outDataRefs);
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/*
+ * XPLMDataRefInfo_t
+ * 
+ * The XPLMDataRefInfo_t structure contains all of the information about a
+ * single data ref.  The structure can be expanded in future SDK APIs to
+ * include more features. Always set the structSize member to the size of 
+ * your struct in bytes!
+ *
+ */
+typedef struct {
+    /* Used to inform XPLMGetDatarefInfo() of the SDK version you compiled        *
+     * against; should always be set to sizeof(XPLMDataRefInfo_t)                 */
+     int                       structSize;
+    /* The full name/path of the data ref                                         */
+     const char *              name;
+     XPLMDataTypeID            type;
+    /* TRUE if the data ref permits writing to it. FALSE if it's read-only.       */
+     int                       writable;
+    /* The handle to the plugin that registered this dataref.                     */
+     XPLMPluginID              owner;
+} XPLMDataRefInfo_t;
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/*
+ * XPLMGetDataRefInfo
+ * 
+ * Give a data ref, this routine returns a populated struct containing the
+ * available information about the dataref.
+ *
+ */
+XPLM_API void       XPLMGetDataRefInfo(
+                         XPLMDataRef          inDataRef,
+                         XPLMDataRefInfo_t *  outInfo);
+#endif /* XPLM400 */
+
+/*
+ * XPLMFindDataRef
+ * 
+ * Given a C-style string that names the dataref, this routine looks up the
+ * actual opaque XPLMDataRef that you use to read and write the data. The
+ * string names for datarefs are published on the X-Plane SDK web site.
+ * 
+ * This function returns NULL if the dataref cannot be found.
+ * 
+ * NOTE: this function is relatively expensive; save the XPLMDataRef this
+ * function returns for future use. Do not look up your dataref by string
+ * every time you need to read or write it.
+ *
+ */
+XPLM_API XPLMDataRef XPLMFindDataRef(
+                         const char *         inDataRefName);
+
+/*
+ * XPLMCanWriteDataRef
+ * 
+ * Given a dataref, this routine returns true if you can successfully set the
+ * data, false otherwise. Some datarefs are read-only.
+ * 
+ * NOTE: even if a dataref is marked writable, it may not act writable.  This
+ * can happen for datarefs that X-Plane writes to on every frame of
+ * simulation.  In some cases, the dataref is writable but you have to set a
+ * separate "override" dataref to 1 to stop X-Plane from writing it.
+ *
+ */
+XPLM_API int        XPLMCanWriteDataRef(
+                         XPLMDataRef          inDataRef);
+
+/*
+ * XPLMIsDataRefGood
+ * 
+ * This function returns true if the passed in handle is a valid dataref that
+ * is not orphaned.
+ * 
+ * Note: there is normally no need to call this function; datarefs returned by
+ * XPLMFindDataRef remain valid (but possibly orphaned) unless there is a
+ * complete plugin reload (in which case your plugin is reloaded anyway).
+ * Orphaned datarefs can be safely read and return 0. Therefore you never need
+ * to call XPLMIsDataRefGood to 'check' the safety of a dataref.
+ * (XPLMIsDataRefGood performs some slow checking of the handle validity, so
+ * it has a perormance cost.)
+ *
+ */
+XPLM_API int        XPLMIsDataRefGood(
+                         XPLMDataRef          inDataRef);
+
+/*
+ * XPLMGetDataRefTypes
+ * 
+ * This routine returns the types of the dataref for accessor use. If a
+ * dataref is available in multiple data types, the bit-wise OR of these types
+ * will be returned.
+ *
+ */
+XPLM_API XPLMDataTypeID XPLMGetDataRefTypes(
+                         XPLMDataRef          inDataRef);
+
+/***************************************************************************
+ * DATA ACCESSORS
+ ***************************************************************************/
+/*
+ * These routines read and write the data references. For each supported data
+ * type there is a reader and a writer.
+ * 
+ * If the dataref is orphaned, the plugin that provides it is disabled or
+ * there is a type mismatch, the functions that read data will return 0 as a
+ * default value or not modify the passed in memory. The plugins that write
+ * data will not write under these circumstances or if the dataref is
+ * read-only.
+ * 
+ * NOTE: to keep the overhead of reading datarefs low, these routines do not
+ * do full validation of a dataref; passing a junk value for a dataref can
+ * result in crashing the sim. The get/set APIs do check for NULL.
+ * 
+ * For array-style datarefs, you specify the number of items to read/write and
+ * the offset into the array; the actual number of items read or written is
+ * returned. This may be less the number requested to prevent an
+ * array-out-of-bounds error.
+ *
+ */
+
+
+/*
+ * XPLMGetDatai
+ * 
+ * Read an integer dataref and return its value. The return value is the
+ * dataref value or 0 if the dataref is NULL or the plugin is disabled.
+ *
+ */
+XPLM_API int        XPLMGetDatai(
+                         XPLMDataRef          inDataRef);
+
+/*
+ * XPLMSetDatai
+ * 
+ * Write a new value to an integer dataref. This routine is a no-op if the
+ * plugin publishing the dataref is disabled, the dataref is NULL, or the
+ * dataref is not writable.
+ *
+ */
+XPLM_API void       XPLMSetDatai(
+                         XPLMDataRef          inDataRef,
+                         int                  inValue);
+
+/*
+ * XPLMGetDataf
+ * 
+ * Read a single precision floating point dataref and return its value. The
+ * return value is the dataref value or 0.0 if the dataref is NULL or the
+ * plugin is disabled.
+ *
+ */
+XPLM_API float      XPLMGetDataf(
+                         XPLMDataRef          inDataRef);
+
+/*
+ * XPLMSetDataf
+ * 
+ * Write a new value to a single precision floating point dataref. This
+ * routine is a no-op if the plugin publishing the dataref is disabled, the
+ * dataref is NULL, or the dataref is not writable.
+ *
+ */
+XPLM_API void       XPLMSetDataf(
+                         XPLMDataRef          inDataRef,
+                         float                inValue);
+
+/*
+ * XPLMGetDatad
+ * 
+ * Read a double precision floating point dataref and return its value. The
+ * return value is the dataref value or 0.0 if the dataref is NULL or the
+ * plugin is disabled.
+ *
+ */
+XPLM_API double     XPLMGetDatad(
+                         XPLMDataRef          inDataRef);
+
+/*
+ * XPLMSetDatad
+ * 
+ * Write a new value to a double precision floating point dataref. This
+ * routine is a no-op if the plugin publishing the dataref is disabled, the
+ * dataref is NULL, or the dataref is not writable.
+ *
+ */
+XPLM_API void       XPLMSetDatad(
+                         XPLMDataRef          inDataRef,
+                         double               inValue);
+
+/*
+ * XPLMGetDatavi
+ * 
+ * Read a part of an integer array dataref. If you pass NULL for outValues,
+ * the routine will return the size of the array, ignoring inOffset and inMax.
+ * 
+ * If outValues is not NULL, then up to inMax values are copied from the
+ * dataref into outValues, starting at inOffset in the dataref. If inMax +
+ * inOffset is larger than the size of the dataref, less than inMax values
+ * will be copied. The number of values copied is returned.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API int        XPLMGetDatavi(
+                         XPLMDataRef          inDataRef,
+                         int *                outValues,              /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMax);
+
+/*
+ * XPLMSetDatavi
+ * 
+ * Write part or all of an integer array dataref. The values passed by
+ * inValues are written into the dataref starting at inOffset. Up to inCount
+ * values are written; however if the values would write past the end of the
+ * dataref array, then fewer values are written.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API void       XPLMSetDatavi(
+                         XPLMDataRef          inDataRef,
+                         int *                inValues,
+                         int                  inoffset,
+                         int                  inCount);
+
+/*
+ * XPLMGetDatavf
+ * 
+ * Read a part of a single precision floating point array dataref. If you pass
+ * NULL for outValues, the routine will return the size of the array, ignoring
+ * inOffset and inMax.
+ * 
+ * If outValues is not NULL, then up to inMax values are copied from the
+ * dataref into outValues, starting at inOffset in the dataref. If inMax +
+ * inOffset is larger than the size of the dataref, less than inMax values
+ * will be copied. The number of values copied is returned.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API int        XPLMGetDatavf(
+                         XPLMDataRef          inDataRef,
+                         float *              outValues,              /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMax);
+
+/*
+ * XPLMSetDatavf
+ * 
+ * Write part or all of a single precision floating point array dataref. The
+ * values passed by inValues are written into the dataref starting at
+ * inOffset. Up to inCount values are written; however if the values would
+ * write past the end of the dataref array, then fewer values are written.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API void       XPLMSetDatavf(
+                         XPLMDataRef          inDataRef,
+                         float *              inValues,
+                         int                  inoffset,
+                         int                  inCount);
+
+/*
+ * XPLMGetDatab
+ * 
+ * Read a part of a byte array dataref. If you pass NULL for outValues, the
+ * routine will return the size of the array, ignoring inOffset and inMax.
+ * 
+ * If outValues is not NULL, then up to inMax values are copied from the
+ * dataref into outValues, starting at inOffset in the dataref. If inMax +
+ * inOffset is larger than the size of the dataref, less than inMax values
+ * will be copied. The number of values copied is returned.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API int        XPLMGetDatab(
+                         XPLMDataRef          inDataRef,
+                         void *               outValue,               /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMaxBytes);
+
+/*
+ * XPLMSetDatab
+ * 
+ * Write part or all of a byte array dataref. The values passed by inValues
+ * are written into the dataref starting at inOffset. Up to inCount values are
+ * written; however if the values would write "off the end" of the dataref
+ * array, then fewer values are written.
+ * 
+ * Note: the semantics of array datarefs are entirely implemented by the
+ * plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+ * above description is how these datarefs are intended to work, but a rogue
+ * plugin may have different behavior.
+ *
+ */
+XPLM_API void       XPLMSetDatab(
+                         XPLMDataRef          inDataRef,
+                         void *               inValue,
+                         int                  inOffset,
+                         int                  inLength);
+
+/***************************************************************************
+ * PUBLISHING YOUR PLUGIN'S DATA
+ ***************************************************************************/
+/*
+ * These functions allow you to create data references that other plug-ins and
+ * X-Plane can access via the above data access APIs. Data references
+ * published by other plugins operate the same as ones published by X-Plane in
+ * all manners except that your data reference will not be available to other
+ * plugins if/when your plugin is disabled.
+ * 
+ * You share data by registering data provider callback functions. When a
+ * plug-in requests your data, these callbacks are then called. You provide
+ * one callback to return the value when a plugin 'reads' it and another to
+ * change the value when a plugin 'writes' it.
+ * 
+ * Important: you must pick a prefix for your datarefs other than "sim/" -
+ * this prefix is reserved for X-Plane. The X-Plane SDK website contains a
+ * registry where authors can select a unique first word for dataref names, to
+ * prevent dataref collisions between plugins.
+ *
+ */
+
+
+/*
+ * XPLMGetDatai_f
+ * 
+ * Data provider function pointers.
+ * 
+ * These define the function pointers you provide to get or set data. Note
+ * that you are passed a generic pointer for each one. This is the same
+ * pointer you pass in your register routine; you can use it to locate plugin
+ * variables, etc.
+ * 
+ * The semantics of your callbacks are the same as the dataref accessors above
+ * - basically routines like XPLMGetDatai are just pass-throughs from a caller
+ * to your plugin. Be particularly mindful in implementing array dataref
+ * read-write accessors; you are responsible for avoiding overruns, supporting
+ * offset read/writes, and handling a read with a NULL buffer.
+ *
+ */
+typedef int (* XPLMGetDatai_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMSetDatai_f
+ *
+ */
+typedef void (* XPLMSetDatai_f)(
+                         void *               inRefcon,
+                         int                  inValue);
+
+/*
+ * XPLMGetDataf_f
+ *
+ */
+typedef float (* XPLMGetDataf_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMSetDataf_f
+ *
+ */
+typedef void (* XPLMSetDataf_f)(
+                         void *               inRefcon,
+                         float                inValue);
+
+/*
+ * XPLMGetDatad_f
+ *
+ */
+typedef double (* XPLMGetDatad_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMSetDatad_f
+ *
+ */
+typedef void (* XPLMSetDatad_f)(
+                         void *               inRefcon,
+                         double               inValue);
+
+/*
+ * XPLMGetDatavi_f
+ *
+ */
+typedef int (* XPLMGetDatavi_f)(
+                         void *               inRefcon,
+                         int *                outValues,              /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMax);
+
+/*
+ * XPLMSetDatavi_f
+ *
+ */
+typedef void (* XPLMSetDatavi_f)(
+                         void *               inRefcon,
+                         int *                inValues,
+                         int                  inOffset,
+                         int                  inCount);
+
+/*
+ * XPLMGetDatavf_f
+ *
+ */
+typedef int (* XPLMGetDatavf_f)(
+                         void *               inRefcon,
+                         float *              outValues,              /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMax);
+
+/*
+ * XPLMSetDatavf_f
+ *
+ */
+typedef void (* XPLMSetDatavf_f)(
+                         void *               inRefcon,
+                         float *              inValues,
+                         int                  inOffset,
+                         int                  inCount);
+
+/*
+ * XPLMGetDatab_f
+ *
+ */
+typedef int (* XPLMGetDatab_f)(
+                         void *               inRefcon,
+                         void *               outValue,               /* Can be NULL */
+                         int                  inOffset,
+                         int                  inMaxLength);
+
+/*
+ * XPLMSetDatab_f
+ *
+ */
+typedef void (* XPLMSetDatab_f)(
+                         void *               inRefcon,
+                         void *               inValue,
+                         int                  inOffset,
+                         int                  inLength);
+
+/*
+ * XPLMRegisterDataAccessor
+ * 
+ * This routine creates a new item of data that can be read and written. Pass
+ * in the data's full name for searching, the type(s) of the data for
+ * accessing, and whether the data can be written to. For each data type you
+ * support, pass in a read accessor function and a write accessor function if
+ * necessary. Pass NULL for data types you do not support or write accessors
+ * if you are read-only.
+ * 
+ * You are returned a dataref for the new item of data created. You can use
+ * this dataref to unregister your data later or read or write from it.
+ *
+ */
+XPLM_API XPLMDataRef XPLMRegisterDataAccessor(
+                         const char *         inDataName,
+                         XPLMDataTypeID       inDataType,
+                         int                  inIsWritable,
+                         XPLMGetDatai_f       inReadInt,
+                         XPLMSetDatai_f       inWriteInt,
+                         XPLMGetDataf_f       inReadFloat,
+                         XPLMSetDataf_f       inWriteFloat,
+                         XPLMGetDatad_f       inReadDouble,
+                         XPLMSetDatad_f       inWriteDouble,
+                         XPLMGetDatavi_f      inReadIntArray,
+                         XPLMSetDatavi_f      inWriteIntArray,
+                         XPLMGetDatavf_f      inReadFloatArray,
+                         XPLMSetDatavf_f      inWriteFloatArray,
+                         XPLMGetDatab_f       inReadData,
+                         XPLMSetDatab_f       inWriteData,
+                         void *               inReadRefcon,
+                         void *               inWriteRefcon);
+
+/*
+ * XPLMUnregisterDataAccessor
+ * 
+ * Use this routine to unregister any data accessors you may have registered.
+ * You unregister a dataref by the XPLMDataRef you get back from registration.
+ * Once you unregister a dataref, your function pointer will not be called
+ * anymore.
+ *
+ */
+XPLM_API void       XPLMUnregisterDataAccessor(
+                         XPLMDataRef          inDataRef);
+
+/***************************************************************************
+ * SHARING DATA BETWEEN MULTIPLE PLUGINS
+ ***************************************************************************/
+/*
+ * The data reference registration APIs from the previous section allow a
+ * plugin to publish data in a one-owner manner; the plugin that publishes the
+ * data reference owns the real memory that the dataref uses. This is
+ * satisfactory for most cases, but there are also cases where plugins need to
+ * share actual data.
+ * 
+ * With a shared data reference, no one plugin owns the actual memory for the
+ * data reference; the plugin SDK allocates that for you. When the first
+ * plugin asks to 'share' the data, the memory is allocated. When the data is
+ * changed, every plugin that is sharing the data is notified.
+ * 
+ * Shared data references differ from the 'owned' data references from the
+ * previous section in a few ways:
+ * 
+ * * With shared data references, any plugin can create the data reference;
+ *   with owned plugins one plugin must create the data reference and others
+ *   subscribe. (This can be a problem if you don't know which set of plugins
+ *   will be present).
+ * 
+ * * With shared data references, every plugin that is sharing the data is
+ *   notified when the data is changed. With owned data references, only the
+ *   one owner is notified when the data is changed.
+ * 
+ * * With shared data references, you cannot access the physical memory of the
+ *   data reference; you must use the XPLMGet... and XPLMSet... APIs. With an
+ *   owned data reference, the one owning data reference can manipulate the
+ *   data reference's memory in any way it sees fit.
+ * 
+ * Shared data references solve two problems: if you need to have a data
+ * reference used by several plugins but do not know which plugins will be
+ * installed, or if all plugins sharing data need to be notified when that
+ * data is changed, use shared data references.
+ *
+ */
+
+
+/*
+ * XPLMDataChanged_f
+ * 
+ * An XPLMDataChanged_f is a callback that the XPLM calls whenever any other
+ * plug-in modifies shared data. A refcon you provide is passed back to help
+ * identify which data is being changed. In response, you may want to call one
+ * of the XPLMGetDataxxx routines to find the new value of the data.
+ *
+ */
+typedef void (* XPLMDataChanged_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMShareData
+ * 
+ * This routine connects a plug-in to shared data, creating the shared data if
+ * necessary. inDataName is a standard path for the dataref, and inDataType
+ * specifies the type. This function will create the data if it does not
+ * exist. If the data already exists but the type does not match, an error is
+ * returned, so it is important that plug-in authors collaborate to establish
+ * public standards for shared data.
+ * 
+ * If a notificationFunc is passed in and is not NULL, that notification
+ * function will be called whenever the data is modified. The notification
+ * refcon will be passed to it. This allows your plug-in to know which shared
+ * data was changed if multiple shared data are handled by one callback, or if
+ * the plug-in does not use global variables.
+ * 
+ * A one is returned for successfully creating or finding the shared data; a
+ * zero if the data already exists but is of the wrong type.
+ *
+ */
+XPLM_API int        XPLMShareData(
+                         const char *         inDataName,
+                         XPLMDataTypeID       inDataType,
+                         XPLMDataChanged_f    inNotificationFunc,
+                         void *               inNotificationRefcon);
+
+/*
+ * XPLMUnshareData
+ * 
+ * This routine removes your notification function for shared data. Call it
+ * when done with the data to stop receiving change notifications. Arguments
+ * must match XPLMShareData. The actual memory will not necessarily be freed,
+ * since other plug-ins could be using it.
+ *
+ */
+XPLM_API int        XPLMUnshareData(
+                         const char *         inDataName,
+                         XPLMDataTypeID       inDataType,
+                         XPLMDataChanged_f    inNotificationFunc,
+                         void *               inNotificationRefcon);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMDefs.h b/SDK/CHeaders/XPLM/XPLMDefs.h
new file mode 100644
index 0000000..7ad9b89
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMDefs.h
@@ -0,0 +1,571 @@
+#ifndef _XPLMDefs_h_
+#define _XPLMDefs_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMDefs
+ ***************************************************************************/
+/*
+ * This file is contains the cross-platform and basic definitions for the
+ * X-Plane SDK.
+ * 
+ * The preprocessor macros APL, LIN and IBM must be defined to specify the
+ * compilation target; define APL to 1 to compile on Mac, IBM to 1 to compile
+ * on Windows and LIN to 1 to compile on Linux. Only one compilation target
+ * may be used at a time. You must specify these macro definitions before
+ * including XPLMDefs.h or any other XPLM headers.  You can do this using the
+ * -D command line option or a preprocessor header.
+ *
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if IBM
+#include <windows.h>
+#endif
+#include <stdint.h>
+/***************************************************************************
+ * DLL Definitions
+ ***************************************************************************/
+/*
+ * These definitions control the importing and exporting of functions within
+ * the DLL.
+ * 
+ * You can prefix your five required callbacks with the PLUGIN_API macro to
+ * declare them as exported C functions.  The XPLM_API macro identifies
+ * functions that are provided to you via the plugin SDK.  (Link against
+ * XPLM.lib to use these functions.)
+ *
+ */
+
+
+#ifdef __cplusplus
+	#if APL
+        #if __GNUC__ >= 4
+            #define PLUGIN_API extern "C" __attribute__((visibility("default")))
+        #elif __MACH__
+			#define PLUGIN_API extern "C"
+		#else		
+			#define PLUGIN_API extern "C" __declspec(dllexport)
+		#endif
+	#elif IBM
+		#define PLUGIN_API extern "C" __declspec(dllexport)
+	#elif LIN
+		#if __GNUC__ >= 4
+			#define PLUGIN_API extern "C" __attribute__((visibility("default")))
+		#else
+			#define PLUGIN_API extern "C"
+		#endif
+	#else
+		#error "Platform not defined!"
+	#endif
+#else
+	#if APL
+        #if __GNUC__ >= 4
+            #define PLUGIN_API __attribute__((visibility("default")))
+        #elif __MACH__
+			#define PLUGIN_API 
+		#else
+			#define PLUGIN_API __declspec(dllexport)
+		#endif		
+	#elif IBM
+		#define PLUGIN_API __declspec(dllexport)
+	#elif LIN
+        #if __GNUC__ >= 4
+            #define PLUGIN_API __attribute__((visibility("default")))
+		#else
+			#define PLUGIN_API
+		#endif		
+	#else
+		#error "Platform not defined!"
+	#endif
+#endif
+
+#if APL
+	#if XPLM
+        #if __GNUC__ >= 4
+            #define XPLM_API __attribute__((visibility("default")))
+        #elif __MACH__
+			#define XPLM_API 
+		#else
+			#define XPLM_API __declspec(dllexport)
+		#endif
+	#else
+		#define XPLM_API 
+	#endif
+#elif IBM
+	#if XPLM
+		#define XPLM_API __declspec(dllexport)
+	#else
+		#define XPLM_API __declspec(dllimport)
+	#endif
+#elif LIN
+	#if XPLM
+		#if __GNUC__ >= 4
+            #define XPLM_API __attribute__((visibility("default")))
+		#else
+			#define XPLM_API
+		#endif
+	#else
+		#define XPLM_API
+	#endif	
+#else
+	#error "Platform not defined!"
+#endif
+
+/***************************************************************************
+ * GLOBAL DEFINITIONS
+ ***************************************************************************/
+/*
+ * These definitions are used in all parts of the SDK.
+ *
+ */
+
+
+/*
+ * XPLMPluginID
+ * 
+ * Each plug-in is identified by a unique integer ID.  This ID can be used to
+ * disable or enable a plug-in, or discover what plug-in is 'running' at the
+ * time.  A plug-in ID is unique within the currently running instance of
+ * X-Plane unless plug-ins are reloaded.  Plug-ins may receive a different
+ * unique ID each time they are loaded. This includes the unloading and
+ * reloading of plugins that are part of the user's aircraft.
+ * 
+ * For persistent identification of plug-ins, use XPLMFindPluginBySignature in
+ * XPLMUtiltiies.h .
+ * 
+ * -1 indicates no plug-in.
+ *
+ */
+typedef int XPLMPluginID;
+
+/* No plugin.                                                                 */
+#define XPLM_NO_PLUGIN_ID    (-1)
+
+/* X-Plane itself                                                             */
+#define XPLM_PLUGIN_XPLANE   (0)
+
+/* The current XPLM revision is 4.1.1 (411).                                  */
+#define kXPLM_Version        (411)
+
+/*
+ * XPLMKeyFlags
+ * 
+ * These bitfields define modifier keys in a platform independent way. When a
+ * key is pressed, a series of messages are sent to your plugin.  The down
+ * flag is set in the first of these messages, and the up flag in the last. 
+ * While the key is held down, messages are sent with neither flag set to
+ * indicate that the key is being held down as a repeated character.
+ * 
+ * The control flag is mapped to the control flag on Macintosh and PC. 
+ * Generally X-Plane uses the control key and not the command key on
+ * Macintosh, providing a consistent interface across platforms that does not
+ * necessarily match the Macintosh user interface guidelines.  There is not
+ * yet a way for plugins to access the Macintosh control keys without using
+ * #ifdefed code.
+ *
+ */
+enum {
+    /* The shift key is down                                                      */
+    xplm_ShiftFlag                           = 1,
+
+    /* The option or alt key is down                                              */
+    xplm_OptionAltFlag                       = 2,
+
+    /* The control key is down                                                    */
+    xplm_ControlFlag                         = 4,
+
+    /* The key is being pressed down                                              */
+    xplm_DownFlag                            = 8,
+
+    /* The key is being released                                                  */
+    xplm_UpFlag                              = 16,
+
+
+};
+typedef int XPLMKeyFlags;
+
+/***************************************************************************
+ * ASCII CONTROL KEY CODES
+ ***************************************************************************/
+/*
+ * These definitions define how various control keys are mapped to ASCII key
+ * codes. Not all key presses generate an ASCII value, so plugin code should
+ * be prepared to see null characters come from the keyboard...this usually
+ * represents a key stroke that has no equivalent ASCII, like a page-down
+ * press.  Use virtual key codes to find these key strokes.
+ * 
+ * ASCII key codes take into account modifier keys; shift keys will affect
+ * capitals and punctuation; control key combinations may have no vaild ASCII
+ * and produce NULL.  To detect control-key combinations, use virtual key
+ * codes, not ASCII keys.
+ *
+ */
+
+
+#define XPLM_KEY_RETURN      13
+
+#define XPLM_KEY_ESCAPE      27
+
+#define XPLM_KEY_TAB         9
+
+#define XPLM_KEY_DELETE      8
+
+#define XPLM_KEY_LEFT        28
+
+#define XPLM_KEY_RIGHT       29
+
+#define XPLM_KEY_UP          30
+
+#define XPLM_KEY_DOWN        31
+
+#define XPLM_KEY_0           48
+
+#define XPLM_KEY_1           49
+
+#define XPLM_KEY_2           50
+
+#define XPLM_KEY_3           51
+
+#define XPLM_KEY_4           52
+
+#define XPLM_KEY_5           53
+
+#define XPLM_KEY_6           54
+
+#define XPLM_KEY_7           55
+
+#define XPLM_KEY_8           56
+
+#define XPLM_KEY_9           57
+
+#define XPLM_KEY_DECIMAL     46
+
+/***************************************************************************
+ * VIRTUAL KEY CODES
+ ***************************************************************************/
+/*
+ * These are cross-platform defines for every distinct keyboard press on the
+ * computer. Every physical key on the keyboard has a virtual key code.  So
+ * the "two" key on the top row of the main keyboard has a different code from
+ * the "two" key on the numeric key pad.  But the 'w' and 'W' character are
+ * indistinguishable by virtual key code because they are the same physical
+ * key (one with and one without the shift key).
+ * 
+ * Use virtual key codes to detect keystrokes that do not have ASCII
+ * equivalents, allow the user to map the numeric keypad separately from the
+ * main keyboard, and detect control key and other modifier-key combinations
+ * that generate ASCII control key sequences (many of which are not available
+ * directly via character keys in the SDK).
+ * 
+ * To assign virtual key codes we started with the Microsoft set but made some
+ * additions and changes.  A few differences:
+ * 
+ * 1. Modifier keys are not available as virtual key codes.  You cannot get
+ *    distinct modifier press and release messages.  Please do not try to use
+ *    modifier keys as regular keys; doing so will almost certainly interfere
+ *    with users' abilities to use the native X-Plane key bindings.
+ * 2. Some keys that do not exist on both Mac and PC keyboards are removed.
+ * 3. Do not assume that the values of these keystrokes are interchangeable
+ *    with MS v-keys.
+ *
+ */
+
+
+#define XPLM_VK_BACK         0x08
+
+#define XPLM_VK_TAB          0x09
+
+#define XPLM_VK_CLEAR        0x0C
+
+#define XPLM_VK_RETURN       0x0D
+
+#define XPLM_VK_ESCAPE       0x1B
+
+#define XPLM_VK_SPACE        0x20
+
+#define XPLM_VK_PRIOR        0x21
+
+#define XPLM_VK_NEXT         0x22
+
+#define XPLM_VK_END          0x23
+
+#define XPLM_VK_HOME         0x24
+
+#define XPLM_VK_LEFT         0x25
+
+#define XPLM_VK_UP           0x26
+
+#define XPLM_VK_RIGHT        0x27
+
+#define XPLM_VK_DOWN         0x28
+
+#define XPLM_VK_SELECT       0x29
+
+#define XPLM_VK_PRINT        0x2A
+
+#define XPLM_VK_EXECUTE      0x2B
+
+#define XPLM_VK_SNAPSHOT     0x2C
+
+#define XPLM_VK_INSERT       0x2D
+
+#define XPLM_VK_DELETE       0x2E
+
+#define XPLM_VK_HELP         0x2F
+
+/* XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)  */
+#define XPLM_VK_0            0x30
+
+#define XPLM_VK_1            0x31
+
+#define XPLM_VK_2            0x32
+
+#define XPLM_VK_3            0x33
+
+#define XPLM_VK_4            0x34
+
+#define XPLM_VK_5            0x35
+
+#define XPLM_VK_6            0x36
+
+#define XPLM_VK_7            0x37
+
+#define XPLM_VK_8            0x38
+
+#define XPLM_VK_9            0x39
+
+/* XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)  */
+#define XPLM_VK_A            0x41
+
+#define XPLM_VK_B            0x42
+
+#define XPLM_VK_C            0x43
+
+#define XPLM_VK_D            0x44
+
+#define XPLM_VK_E            0x45
+
+#define XPLM_VK_F            0x46
+
+#define XPLM_VK_G            0x47
+
+#define XPLM_VK_H            0x48
+
+#define XPLM_VK_I            0x49
+
+#define XPLM_VK_J            0x4A
+
+#define XPLM_VK_K            0x4B
+
+#define XPLM_VK_L            0x4C
+
+#define XPLM_VK_M            0x4D
+
+#define XPLM_VK_N            0x4E
+
+#define XPLM_VK_O            0x4F
+
+#define XPLM_VK_P            0x50
+
+#define XPLM_VK_Q            0x51
+
+#define XPLM_VK_R            0x52
+
+#define XPLM_VK_S            0x53
+
+#define XPLM_VK_T            0x54
+
+#define XPLM_VK_U            0x55
+
+#define XPLM_VK_V            0x56
+
+#define XPLM_VK_W            0x57
+
+#define XPLM_VK_X            0x58
+
+#define XPLM_VK_Y            0x59
+
+#define XPLM_VK_Z            0x5A
+
+#define XPLM_VK_NUMPAD0      0x60
+
+#define XPLM_VK_NUMPAD1      0x61
+
+#define XPLM_VK_NUMPAD2      0x62
+
+#define XPLM_VK_NUMPAD3      0x63
+
+#define XPLM_VK_NUMPAD4      0x64
+
+#define XPLM_VK_NUMPAD5      0x65
+
+#define XPLM_VK_NUMPAD6      0x66
+
+#define XPLM_VK_NUMPAD7      0x67
+
+#define XPLM_VK_NUMPAD8      0x68
+
+#define XPLM_VK_NUMPAD9      0x69
+
+#define XPLM_VK_MULTIPLY     0x6A
+
+#define XPLM_VK_ADD          0x6B
+
+#define XPLM_VK_SEPARATOR    0x6C
+
+#define XPLM_VK_SUBTRACT     0x6D
+
+#define XPLM_VK_DECIMAL      0x6E
+
+#define XPLM_VK_DIVIDE       0x6F
+
+#define XPLM_VK_F1           0x70
+
+#define XPLM_VK_F2           0x71
+
+#define XPLM_VK_F3           0x72
+
+#define XPLM_VK_F4           0x73
+
+#define XPLM_VK_F5           0x74
+
+#define XPLM_VK_F6           0x75
+
+#define XPLM_VK_F7           0x76
+
+#define XPLM_VK_F8           0x77
+
+#define XPLM_VK_F9           0x78
+
+#define XPLM_VK_F10          0x79
+
+#define XPLM_VK_F11          0x7A
+
+#define XPLM_VK_F12          0x7B
+
+#define XPLM_VK_F13          0x7C
+
+#define XPLM_VK_F14          0x7D
+
+#define XPLM_VK_F15          0x7E
+
+#define XPLM_VK_F16          0x7F
+
+#define XPLM_VK_F17          0x80
+
+#define XPLM_VK_F18          0x81
+
+#define XPLM_VK_F19          0x82
+
+#define XPLM_VK_F20          0x83
+
+#define XPLM_VK_F21          0x84
+
+#define XPLM_VK_F22          0x85
+
+#define XPLM_VK_F23          0x86
+
+#define XPLM_VK_F24          0x87
+
+/* The following definitions are extended and are not based on the Microsoft  *
+ * key set.                                                                   */
+#define XPLM_VK_EQUAL        0xB0
+
+#define XPLM_VK_MINUS        0xB1
+
+#define XPLM_VK_RBRACE       0xB2
+
+#define XPLM_VK_LBRACE       0xB3
+
+#define XPLM_VK_QUOTE        0xB4
+
+#define XPLM_VK_SEMICOLON    0xB5
+
+#define XPLM_VK_BACKSLASH    0xB6
+
+#define XPLM_VK_COMMA        0xB7
+
+#define XPLM_VK_SLASH        0xB8
+
+#define XPLM_VK_PERIOD       0xB9
+
+#define XPLM_VK_BACKQUOTE    0xBA
+
+#define XPLM_VK_ENTER        0xBB
+
+#define XPLM_VK_NUMPAD_ENT   0xBC
+
+#define XPLM_VK_NUMPAD_EQ    0xBD
+
+/*
+ * XPLMFixedString150_t
+ * 
+ * A container for a fixed-size string buffer of 150 characters.
+ *
+ */
+typedef struct {
+    /* The size of the struct.                                                    */
+     char                      buffer[150];
+} XPLMFixedString150_t;
+#if defined(XPLM200)
+/*
+ * XPLMCursorStatus
+ * 
+ * XPLMCursorStatus describes how you would like X-Plane to manage the cursor.
+ * See XPLMHandleCursor_f for more info.
+ *
+ */
+enum {
+    /* X-Plane manages the cursor normally, plugin does not affect the cusrsor.   */
+    xplm_CursorDefault                       = 0,
+
+    /* X-Plane hides the cursor.                                                  */
+    xplm_CursorHidden                        = 1,
+
+    /* X-Plane shows the cursor as the default arrow.                             */
+    xplm_CursorArrow                         = 2,
+
+    /* X-Plane shows the cursor but lets you select an OS cursor.                 */
+    xplm_CursorCustom                        = 3,
+
+
+};
+typedef int XPLMCursorStatus;
+#endif /* XPLM200 */
+/*
+ * XPLMMouseStatus
+ * 
+ *     When the mouse is clicked, your mouse click routine is called
+ *     repeatedly.  It is first called with the mouse down message.  It is
+ *     then called zero or more times with the mouse-drag message, and finally
+ *     it is called once with the mouse up message.  All of these messages
+ *     will be directed to the same window; you are guaranteed to not receive
+ *     a drag or mouse-up event without first receiving the corresponding
+ *     mouse-down.
+ *
+ */
+enum {
+    xplm_MouseDown                           = 1,
+
+    xplm_MouseDrag                           = 2,
+
+    xplm_MouseUp                             = 3,
+
+
+};
+typedef int XPLMMouseStatus;
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMDisplay.h b/SDK/CHeaders/XPLM/XPLMDisplay.h
new file mode 100644
index 0000000..ba88487
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMDisplay.h
@@ -0,0 +1,2191 @@
+#ifndef _XPLMDisplay_h_
+#define _XPLMDisplay_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMDisplay
+ ***************************************************************************/
+/*
+ * This API provides the basic hooks to draw in X-Plane and create user
+ * interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in
+ * manager takes care of properly setting up the OpenGL context and matrices. 
+ * You do not decide when in your code's execution to draw; X-Plane tells you
+ * (via callbacks) when it is ready to have your plugin draw.
+ * 
+ * X-Plane's drawing strategy is straightforward: every "frame" the screen is
+ * rendered by drawing the 3-D scene (dome, ground, objects, airplanes, etc.)
+ * and then drawing the cockpit on top of it.  Alpha blending is used to
+ * overlay the cockpit over the world (and the gauges over the panel, etc.).
+ * X-Plane user interface elements (including windows like the map, the main
+ * menu, etc.) are then drawn on top of the cockpit.
+ * 
+ * There are two ways you can draw: directly and in a window.
+ * 
+ * Direct drawing (deprecated!---more on that below) involves drawing to the
+ * screen before or after X-Plane finishes a phase of drawing.  When you draw
+ * directly, you can specify whether X-Plane is to complete this phase or not.
+ * This allows you to do three things: draw before X-Plane does (under it),
+ * draw after X-Plane does (over it), or draw instead of X-Plane.
+ * 
+ * To draw directly, you register a callback and specify which phase you want
+ * to intercept.  The plug-in manager will call you over and over to draw that
+ * phase.
+ * 
+ * Direct drawing allows you to override scenery, panels, or anything.  Note
+ * that you cannot assume that you are the only plug-in drawing at this phase.
+ * 
+ * Direct drawing is deprecated; at some point in the X-Plane 11 run, it will
+ * likely become unsupported entirely as X-Plane transitions from OpenGL to
+ * modern graphics API backends (e.g., Vulkan, Metal, etc.). In the long term,
+ * plugins should use the XPLMInstance API for drawing 3-D objects---this will
+ * be much more efficient than general 3-D OpenGL drawing, and it will
+ * actually be supported by the new graphics backends. We do not yet know what
+ * the post-transition API for generic 3-D drawing will look like (if it
+ * exists at all).
+ * 
+ * In contrast to direct drawing, window drawing provides a higher level
+ * functionality. With window drawing, you create a 2-D window that takes up a
+ * portion of the screen. Window drawing is always two dimensional.  Window
+ * drawing is depth controlled; you can specify that you want your window to
+ * be brought on top, and other plug-ins may put their window on top of you. 
+ * Window drawing also allows you to sign up for key presses and receive mouse
+ * clicks.
+ * 
+ * Drawing into the screen of an avionics device, like a GPS or a Primary
+ * Flight Display, is a way  to extend or replace X-Plane's avionics. Most
+ * screens can be displayed both in a 3d cockpit or 
+ * 2d panel, and also in separate popup windows. By installing drawing
+ *  callbacks for a certain avionics  device, you can change or extend the
+ *  appearance of that device regardless whether it's installed  in a 3d
+ *  cockpit or used in a separate display for home cockpits because you leave
+ *  the window managing to X-Plane.
+ * 
+ * There are three ways to get keystrokes:
+ * 
+ * 1. If you create a window, the window can take keyboard focus.  It will
+ *    then receive all keystrokes.  If no window has focus, X-Plane receives
+ *    keystrokes.  Use this to implement typing in dialog boxes, etc.  Only
+ *    one window may have focus at a time; your window will be notified if it
+ *    loses focus.
+ * 2. If you need low level access to the keystroke stream, install a key
+ *    sniffer.  Key sniffers can be installed above everything or right in
+ *    front of the sim.
+ * 3. If you would like to associate key strokes with commands/functions in
+ *    your plug-in, you should simply register a command (via
+ *    XPLMCreateCommand()) and allow users to bind whatever key they choose to
+ *    that command. Another (now deprecated) method of doing so is to use a
+ *    hot key---a key-specific callback.  Hotkeys are sent based on virtual
+ *    key strokes, so any key may be distinctly mapped with any modifiers. 
+ *    Hot keys can be remapped by other plug-ins.  As a plug-in, you don't
+ *    have to worry about what your hot key ends up mapped to; other plug-ins
+ *    may provide a UI for remapping keystrokes.  So hotkeys allow a user to
+ *    resolve conflicts and customize keystrokes.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * DRAWING CALLBACKS
+ ***************************************************************************/
+/*
+ * Basic drawing callbacks, for low level intercepting of X-Plane's render
+ * loop. The purpose of drawing callbacks is to provide targeted additions or
+ * replacements to X-Plane's graphics environment (for example, to add extra
+ * custom objects, or replace drawing of the AI aircraft).  Do not assume that
+ * the drawing callbacks will be called in the order implied by the
+ * enumerations. Also do not assume that each drawing phase ends before
+ * another begins; they may be nested.
+ * 
+ * Note that all APIs in this section are deprecated, and will likely be
+ * removed during the X-Plane 11 run as part of the transition to
+ * Vulkan/Metal/etc. See the XPLMInstance API for future-proof drawing of 3-D
+ * objects.
+ *
+ */
+
+
+/*
+ * XPLMDrawingPhase
+ * 
+ * This constant indicates which part of drawing we are in.  Drawing is done
+ * from the back to the front.  We get a callback before or after each item.
+ * Metaphases provide access to the beginning and end of the 3d (scene) and
+ * 2d (cockpit) drawing in a manner that is independent of new phases added
+ *  via X-Plane implementation.
+ * 
+ * **NOTE**: As of XPLM302 the legacy 3D drawing phases (xplm_Phase_FirstScene
+ *   to xplm_Phase_LastScene) are deprecated. When running under X-Plane 11.50
+ *   with the modern Vulkan or Metal backend, X-Plane will no longer call
+ *   these drawing phases. There is a new drawing phase, xplm_Phase_Modern3D,
+ *   which is supported under OpenGL and Vulkan which is called out roughly
+ *   where the old before xplm_Phase_Airplanes phase was for blending. This
+ *   phase is *NOT* supported under Metal and comes with potentially
+ *   substantial performance overhead. Please do *NOT* opt into this phase if
+ *   you don't do any actual drawing that requires the depth buffer in some
+ *   way!
+ * 
+ * **WARNING**: As X-Plane's scenery evolves, some drawing phases may cease to
+ *   exist and new ones may be invented.  If you need a particularly specific
+ *   use of these codes, consult Austin and/or be prepared to revise your code
+ *   as X-Plane evolves.
+ *
+ */
+enum {
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. This is the earliest point at which you can draw *
+     * in 3-d.                                                                    */
+    xplm_Phase_FirstScene                    = 0,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. Drawing of land and water.                       */
+    xplm_Phase_Terrain                       = 5,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. Drawing runways and other airport detail.        */
+    xplm_Phase_Airports                      = 10,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. Drawing roads, trails, trains, etc.              */
+    xplm_Phase_Vectors                       = 15,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. 3-d objects (houses, smokestacks, etc.           */
+    xplm_Phase_Objects                       = 20,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. External views of airplanes, both yours and the  *
+     * AI aircraft.                                                               */
+    xplm_Phase_Airplanes                     = 25,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated as of XPLM302. This is the last point at which you can draw in  *
+     * 3-d.                                                                       */
+    xplm_Phase_LastScene                     = 30,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM302)
+    /* A chance to do modern 3D drawing.                                          */
+    xplm_Phase_Modern3D                      = 31,
+
+#endif /* XPLM302 */
+    /* This is the first phase where you can draw in 2-d.                         */
+    xplm_Phase_FirstCockpit                  = 35,
+
+    /* The non-moving parts of the aircraft panel.                                */
+    xplm_Phase_Panel                         = 40,
+
+    /* The moving parts of the aircraft panel.                                    */
+    xplm_Phase_Gauges                        = 45,
+
+    /* Floating windows from plugins.                                             */
+    xplm_Phase_Window                        = 50,
+
+    /* The last chance to draw in 2d.                                             */
+    xplm_Phase_LastCockpit                   = 55,
+
+#if defined(XPLM200)
+    /* Removed as of XPLM300; Use the full-blown XPLMMap API instead.             */
+    xplm_Phase_LocalMap3D                    = 100,
+
+#endif /* XPLM200 */
+#if defined(XPLM200)
+    /* Removed as of XPLM300; Use the full-blown XPLMMap API instead.             */
+    xplm_Phase_LocalMap2D                    = 101,
+
+#endif /* XPLM200 */
+#if defined(XPLM200)
+    /* Removed as of XPLM300; Use the full-blown XPLMMap API instead.             */
+    xplm_Phase_LocalMapProfile               = 102,
+
+#endif /* XPLM200 */
+
+};
+typedef int XPLMDrawingPhase;
+
+/*
+ * XPLMDrawCallback_f
+ * 
+ * This is the prototype for a low level drawing callback.  You are passed in
+ * the phase and whether it is before or after.  If you are before the phase,
+ * return 1 to let X-Plane draw or 0 to suppress X-Plane drawing.  If you are
+ * after the phase the return value is ignored.
+ * 
+ * Refcon is a unique value that you specify when registering the callback,
+ * allowing you to slip a pointer to your own data to the callback.
+ * 
+ * Upon entry the OpenGL context will be correctly set up for you and OpenGL
+ * will be in 'local' coordinates for 3d drawing and panel coordinates for 2d
+ * drawing.  The OpenGL state (texturing, etc.) will be unknown.
+ *
+ */
+typedef int (* XPLMDrawCallback_f)(
+                         XPLMDrawingPhase     inPhase,
+                         int                  inIsBefore,
+                         void *               inRefcon);
+
+/*
+ * XPLMRegisterDrawCallback
+ * 
+ * This routine registers a low level drawing callback.  Pass in the phase you
+ * want to be called for and whether you want to be called before or after. 
+ * This routine returns 1 if the registration was successful, or 0 if the
+ * phase does not exist in this version of X-Plane.  You may register a
+ * callback multiple times for the same or different phases as long as the
+ * refcon is unique each time.
+ * 
+ * Note that this function will likely be removed during the X-Plane 11 run as
+ * part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for
+ * future-proof drawing of 3-D objects.
+ *
+ */
+XPLM_API int        XPLMRegisterDrawCallback(
+                         XPLMDrawCallback_f   inCallback,
+                         XPLMDrawingPhase     inPhase,
+                         int                  inWantsBefore,
+                         void *               inRefcon);
+
+/*
+ * XPLMUnregisterDrawCallback
+ * 
+ * This routine unregisters a draw callback.  You must unregister a callback
+ * for each time you register a callback if you have registered it multiple
+ * times with different refcons.  The routine returns 1 if it can find the
+ * callback to unregister, 0 otherwise.
+ * 
+ * Note that this function will likely be removed during the X-Plane 11 run as
+ * part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for
+ * future-proof drawing of 3-D objects.
+ *
+ */
+XPLM_API int        XPLMUnregisterDrawCallback(
+                         XPLMDrawCallback_f   inCallback,
+                         XPLMDrawingPhase     inPhase,
+                         int                  inWantsBefore,
+                         void *               inRefcon);
+
+#if defined(XPLM400)
+/***************************************************************************
+ * AVIONICS API
+ ***************************************************************************/
+/*
+ * The Avionics API allows you to customize the drawing and behaviour of the
+ * built-in cockpit devices (GNS, G1000, etc.), and create your own cockpit
+ * devices. For built-in devices, you can draw before and/or after X-Plane
+ * does, and optionally prevent X-Plane from drawing the screen at all.
+ * Customized built-in devices and custom devices are available in the 3D
+ * cockpit as well as in the form of pop-up/pop-out windows.
+ * 
+ * The API also allows you to receive mouse interaction events for your device
+ * (click down, drag, and up, mouse wheel scroll, cursor) for both screen and
+ * bezel. While these always work when the device is popped-up in its window,
+ * you must add a `ATTR_manip_device` manipulator on top of your screen in
+ * order to receive mouse events from the 3D cockpit.
+ * 
+ * You can also use the avionics API to control the state and location of
+ * cockpit devices' pop-up windows.
+ * 
+ * When working with avionics devices, all co-ordinates you receive when
+ * drawing or dealing with click events are in texels. The x-axis grows right,
+ * the y-axis grows up. In bezel callbacks, the origin is at the bottom left
+ * corner of the bezel. In screen callbacks, the origin is at the bottom-left
+ * of the screen. X-Plane takes care of scaling your screen and bezel if the
+ * user pops out the device's window: you should always draw your screen and
+ * bezel as if they were at the size you specified when registering callbacks
+ * or creating a device.
+ *
+ */
+
+
+/*
+ * XPLMDeviceID
+ * 
+ * This constant indicates the device we want to override or enhance. We can
+ * get a callback before or after each item.
+ *
+ */
+enum {
+    /* GNS430, pilot side.                                                        */
+    xplm_device_GNS430_1                     = 0,
+
+    /* GNS430, copilot side.                                                      */
+    xplm_device_GNS430_2                     = 1,
+
+    /* GNS530, pilot side.                                                        */
+    xplm_device_GNS530_1                     = 2,
+
+    /* GNS530, copilot side.                                                      */
+    xplm_device_GNS530_2                     = 3,
+
+    /* generic airliner CDU, pilot side.                                          */
+    xplm_device_CDU739_1                     = 4,
+
+    /* generic airliner CDU, copilot side.                                        */
+    xplm_device_CDU739_2                     = 5,
+
+    /* G1000 Primary Flight Display, pilot side.                                  */
+    xplm_device_G1000_PFD_1                  = 6,
+
+    /* G1000 Multifunction Display.                                               */
+    xplm_device_G1000_MFD                    = 7,
+
+    /* G1000 Primary Flight Display, copilot side.                                */
+    xplm_device_G1000_PFD_2                  = 8,
+
+    /* Primus CDU, pilot side.                                                    */
+    xplm_device_CDU815_1                     = 9,
+
+    /* Primus CDU, copilot side.                                                  */
+    xplm_device_CDU815_2                     = 10,
+
+    /* Primus Primary Flight Display, pilot side.                                 */
+    xplm_device_Primus_PFD_1                 = 11,
+
+    /* Primus Primary Flight Display, copilot side.                               */
+    xplm_device_Primus_PFD_2                 = 12,
+
+    /* Primus Multifunction Display, pilot side.                                  */
+    xplm_device_Primus_MFD_1                 = 13,
+
+    /* Primus Multifunction Display, copilot side.                                */
+    xplm_device_Primus_MFD_2                 = 14,
+
+    /* Primus Multifunction Display, central.                                     */
+    xplm_device_Primus_MFD_3                 = 15,
+
+    /* Primus Radio Management Unit, pilot side.                                  */
+    xplm_device_Primus_RMU_1                 = 16,
+
+    /* Primus Radio Management Unit, copilot side.                                */
+    xplm_device_Primus_RMU_2                 = 17,
+
+    /* Airbus MCDU, pilot side.                                                   */
+    xplm_device_MCDU_1                       = 18,
+
+    /* Airbus MCDU, copilot side.                                                 */
+    xplm_device_MCDU_2                       = 19,
+
+
+};
+typedef int XPLMDeviceID;
+
+/*
+ * XPLMAvionicsCallback_f
+ * 
+ * This is the prototype for drawing callbacks for customized built-in device.
+ * You are passed in the device you are enhancing/replacing, and (if this is
+ * used for a built-in device that you are customizing) whether it is before
+ * or after X-Plane drawing. If you are before X-Plane, return 1 to let
+ * X-Plane draw or 0 to suppress X-Plane drawing. If you are called after
+ * X-Plane, the return value is ignored.
+ * 
+ * Refcon is a unique value that you specify when registering the callback,
+ * allowing you to slip a pointer to your own data to the callback.
+ * 
+ * Upon entry the OpenGL context will be correctly set up for you and OpenGL
+ * will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+ * etc.) will be unknown.
+ *
+ */
+typedef int (* XPLMAvionicsCallback_f)(
+                         XPLMDeviceID         inDeviceID,
+                         int                  inIsBefore,
+                         void *               inRefcon);
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsMouse_f
+ * 
+ * Mouse click callback for clicks into your screen or (2D-popup) bezel,
+ * useful if the device you are making simulates a touch-screen the user can
+ * click in the 3d cockpit, or if your pop-up's bezel has buttons that the
+ * user can click. Return 1 to consume the event, or 0 to let X-Plane process
+ * it (for stock avionics devices).
+ *
+ */
+typedef int (* XPLMAvionicsMouse_f)(
+                         int                  x,
+                         int                  y,
+                         XPLMMouseStatus      inMouse,
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsMouseWheel_f
+ * 
+ * Mouse wheel callback for scroll actions into your screen or (2D-popup)
+ * bezel, useful if your bezel has knobs that can be turned using the mouse
+ * wheel, or if you want to simulate pinch-to-zoom on a touchscreen. Return 1
+ * to consume the event, or 0 to let X-Plane process it (for stock avionics
+ * devices). The number of "clicks" indicates how far the wheel was turned
+ * since the last callback. The wheel is 0 for the vertical axis or 1 for the
+ * horizontal axis (for OS/mouse combinations that support this).
+ *
+ */
+typedef int (* XPLMAvionicsMouseWheel_f)(
+                         int                  x,
+                         int                  y,
+                         int                  wheel,
+                         int                  clicks,
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsCursor_f
+ * 
+ * Cursor callback that decides which cursor to show when the mouse is over
+ * your screen or (2D-popup) bezel. Return xplm_CursorDefault to let X-Plane
+ * use which cursor to show, or other values to force the cursor to a
+ * particular one (see XPLMCursorStatus).
+ *
+ */
+typedef XPLMCursorStatus (* XPLMAvionicsCursor_f)(
+                         int                  x,
+                         int                  y,
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsKeyboard_f
+ * 
+ * Key callback called when your device is popped up and you've requested to
+ * capture the keyboard.  Return 1 to consume the event, or 0 to let X-Plane
+ * process it (for stock avionics devices).
+ *
+ */
+typedef int (* XPLMAvionicsKeyboard_f)(
+                         char                 inKey,
+                         XPLMKeyFlags         inFlags,
+                         char                 inVirtualKey,
+                         void *               inRefCon,
+                         int                  losingFocus);
+#endif /* XPLM410 */
+
+/*
+ * XPLMAvionicsID
+ * 
+ * This is an opaque identifier for an avionics display that you enhance or
+ * replace.  When you register your callbacks (via
+ * XPLMRegisterAvionicsCallbacksEx()) or create a new device (via
+ * XPLMCreateAvionicsDevice()), you will specify drawing and mouse callbacks,
+ * and get back such a handle.
+ *
+ */
+typedef void * XPLMAvionicsID;
+
+/*
+ * XPLMCustomizeAvionics_t
+ * 
+ * The XPLMCustomizeAvionics_t structure defines all of the parameters used to
+ * replace or  enhance built-in simulator avionics devices using
+ * XPLMRegisterAvionicsCallbacksEx(). The structure will be expanded in future
+ * SDK APIs to include more features. Always set the structSize member to the
+ * size of your struct in bytes!
+ *
+ */
+typedef struct {
+    /* Used to inform XPLMRegisterAvionicsCallbacksEx() of the SDK version you    *
+     * compiled against; should always be set to sizeof(XPLMCustomizeAvionics_t)  */
+     int                       structSize;
+    /* The built-in avionics device to which you want your drawing applied.       */
+     XPLMDeviceID              deviceId;
+    /* The draw callback to be called before X-Plane draws.                       */
+     XPLMAvionicsCallback_f    drawCallbackBefore;
+    /* The draw callback to be called after X-Plane has drawn.                    */
+     XPLMAvionicsCallback_f    drawCallbackAfter;
+#if defined(XPLM410)
+    /* The mouse click callback that is called when the user clicks onto the      *
+     * device's bezel.                                                            */
+     XPLMAvionicsMouse_f       bezelClickCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The mouse click callback that is called when the user clicks onto the      *
+     * device's bezel.                                                            */
+     XPLMAvionicsMouse_f       bezelRightClickCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The callback that is called when the users uses the scroll wheel over the  *
+     * device's bezel.                                                            */
+     XPLMAvionicsMouseWheel_f  bezelScrollCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The callback that lets you determine what cursor should be shown when the  *
+     * mouse is over the device's bezel.                                          */
+     XPLMAvionicsCursor_f      bezelCursorCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The mouse click callback that is called when the user clicks onto the      *
+     * device's screen.                                                           */
+     XPLMAvionicsMouse_f       screenTouchCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The right mouse click callback that is called when the user clicks onto the*
+     * device's screen.                                                           */
+     XPLMAvionicsMouse_f       screenRightTouchCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The callback that is called when the users uses the scroll wheel over the  *
+     * device's screen.                                                           */
+     XPLMAvionicsMouseWheel_f  screenScrollCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The callback that lets you determine what cursor should be shown when the  *
+     * mouse is over the device's screen.                                         */
+     XPLMAvionicsCursor_f      screenCursorCallback;
+#endif /* XPLM410 */
+#if defined(XPLM410)
+    /* The key callback that is called when the user types in the device's popup. */
+     XPLMAvionicsKeyboard_f    keyboardCallback;
+#endif /* XPLM410 */
+    /* A reference which will be passed into each of your draw callbacks. Use this*
+     * to pass information to yourself as needed.                                 */
+     void *                    refcon;
+} XPLMCustomizeAvionics_t;
+
+/*
+ * XPLMRegisterAvionicsCallbacksEx
+ * 
+ * This routine registers your callbacks for a built-in device. This returns a
+ * handle. If the returned handle is NULL, there was a problem interpreting
+ * your input, most likely the struct size was wrong for your SDK version. If
+ * the returned handle is not NULL, your callbacks will be called according to
+ * schedule as long as your plugin is not deactivated, or unloaded, or you
+ * call XPLMUnregisterAvionicsCallbacks().
+ * 
+ * Note that you cannot register new callbacks for a device that is not a
+ * built-in one (for example a device that you have created, or a device
+ * another plugin has created).
+ *
+ */
+XPLM_API XPLMAvionicsID XPLMRegisterAvionicsCallbacksEx(
+                         XPLMCustomizeAvionics_t * inParams);
+
+/*
+ * XPLMGetAvionicsHandle
+ * 
+ * This routine registers no callbacks for a built-in cockpit device, but
+ * returns a handle which allows you to interact with it using the Avionics
+ * Device API. Use this if you do not wish to intercept drawing, clicks and
+ * touchscreen calls to a device, but want to interact with its popup
+ * programmatically. This is equivalent to calling
+ * XPLMRegisterAvionicsCallbackEx() with NULL for all callbacks.
+ *
+ */
+XPLM_API XPLMAvionicsID XPLMGetAvionicsHandle(
+                         XPLMDeviceID         inDeviceID);
+
+/*
+ * XPLMUnregisterAvionicsCallbacks
+ * 
+ * This routine unregisters your callbacks for a built-in device. You should
+ * only call this for handles you acquired from
+ * XPLMRegisterAvionicsCallbacksEx(). They will no longer be called.
+ *
+ */
+XPLM_API void       XPLMUnregisterAvionicsCallbacks(
+                         XPLMAvionicsID       inAvionicsId);
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsScreenCallback_f
+ * 
+ * This is the prototype for drawing callbacks for custom devices' screens.
+ * Refcon is a unique value that you specify when creating the device,
+ * allowing you to slip a pointer to your own data to the callback.
+ * 
+ * Upon entry the OpenGL context will be correctly set up for you and OpenGL
+ * will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+ * etc.) will be unknown. X-Plane does not clear your screen for you between
+ * calls - this means you can re-use portions to save drawing, but otherwise
+ * you must call glClear() to erase the screen's contents.
+ *
+ */
+typedef void (* XPLMAvionicsScreenCallback_f)(
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsBezelCallback_f
+ * 
+ * This is the prototype for drawing callbacks for custom devices' bezel. You
+ * are passed in the red, green, and blue values you can optinally use for
+ * tinting your bezel accoring to ambiant light.
+ * 
+ * Refcon is a unique value that you specify when creating the device,
+ * allowing you to slip a pointer to your own data to the callback.
+ * 
+ * Upon entry the OpenGL context will be correctly set up for you and OpenGL
+ * will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+ * etc.) will be unknown.
+ *
+ */
+typedef void (* XPLMAvionicsBezelCallback_f)(
+                         float                inAmbiantR,
+                         float                inAmbiantG,
+                         float                inAmbiantB,
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsBrightness_f
+ * 
+ * This is the prototype for screen brightness callbacks for custom devices.
+ * If you provide a callback, you can return the ratio of the screen's maximum
+ * brightness that the simulator should use when displaying the screen in the
+ * 3D cockpit.
+ * 
+ * inRheoValue is the current ratio value (between 0 and 1) of the instrument
+ * brightness rheostat to which the device is bound.
+ * 
+ * inAmbientBrightness is the value (between 0 and 1) that the callback should
+ * return for the screen to be at a usable brightness based on ambient light
+ * (if your device has a photo cell and automatically adjusts its brightness,
+ * you can return this and your screen will be at the optimal brightness to be
+ * readable, but not blind the pilot).
+ * 
+ * inBusVoltsRatio is the ratio of the nominal voltage currently present on
+ * the bus to which the device is bound, or -1 if the device is not bound to
+ * the current aircraft.
+ * 
+ * Refcon is a unique value that you specify when creating the device,
+ * allowing you to slip a pointer to your own data to the callback.
+ *
+ */
+typedef float (* XPLMAvionicsBrightness_f)(
+                         float                inRheoValue,
+                         float                inAmbiantBrightness,
+                         float                inBusVoltsRatio,
+                         void *               inRefcon);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMCreateAvionics_t
+ * 
+ * The XPLMCreateAvionics_t structure defines all of the parameters used to
+ * generate your own glass cockpit device by using XPLMCreateAvionicsEx(). The
+ * structure will be expanded in future SDK APIs to include more features.
+ * Always set the structSize member to the size of your struct in bytes!
+ *
+ */
+typedef struct {
+    /* Used to inform XPLMCreateAvionicsEx() of the SDK version you compiled      *
+     * against; should always be set to sizeof(XPLMCreateAvionics_t)              */
+     int                       structSize;
+    /* Width of the device's screen in pixels.                                    */
+     int                       screenWidth;
+    /* Height of the device's screen in pixels.                                   */
+     int                       screenHeight;
+    /* Width of the bezel around your device's screen for 2D pop-ups.             */
+     int                       bezelWidth;
+    /* Height of the bezel around your device's screen for 2D pop-ups.            */
+     int                       bezelHeight;
+    /* The screen's lateral offset into the bezel for 2D pop-ups.                 */
+     int                       screenOffsetX;
+    /* The screen's vertical offset into the bezel for 2D pop-ups.                */
+     int                       screenOffsetY;
+    /* If set to true (1), X-Plane won't call your plugin to re-render the        *
+     * device's screen every frame. Instead, you should tell X-Plane you want to  *
+     * refresh your screen with XPLMAvionicsNeedsDrawing(), and X-Plane will call *
+     * you before rendering the next simulator frame.                             */
+     int                       drawOnDemand;
+    /* The draw callback you will use to draw the 2D-popup bezel. This is called  *
+     * only when the popup window is visible, and X-Plane is about to draw the    *
+     * bezel in it.                                                               */
+     XPLMAvionicsBezelCallback_f bezelDrawCallback;
+    /* The draw callback you will be using to draw into the device's screen       *
+     * framebuffer.                                                               */
+     XPLMAvionicsScreenCallback_f drawCallback;
+    /* The mouse click callback that is called when the user clicks onto your     *
+     * bezel.                                                                     */
+     XPLMAvionicsMouse_f       bezelClickCallback;
+    /* The mouse click callback that is called when the user clicks onto your     *
+     * bezel.                                                                     */
+     XPLMAvionicsMouse_f       bezelRightClickCallback;
+    /* The callback that is called when the users uses the scroll wheel over your *
+     * avionics' bezel.                                                           */
+     XPLMAvionicsMouseWheel_f  bezelScrollCallback;
+    /* The callback that lets you determine what cursor should be shown when the  *
+     * mouse is over your device's bezel.                                         */
+     XPLMAvionicsCursor_f      bezelCursorCallback;
+    /* The mouse click callback that is called when the user clicks onto your     *
+     * screen.                                                                    */
+     XPLMAvionicsMouse_f       screenTouchCallback;
+    /* The right mouse click callback that is called when the user clicks onto    *
+     * your screen.                                                               */
+     XPLMAvionicsMouse_f       screenRightTouchCallback;
+    /* The callback that is called when the users uses the scroll wheel over your *
+     * avionics' screen.                                                          */
+     XPLMAvionicsMouseWheel_f  screenScrollCallback;
+    /* The callback that lets you determine what cursor should be shown when the  *
+     * mouse is over your device's screen.                                        */
+     XPLMAvionicsCursor_f      screenCursorCallback;
+    /* The key callback that is called when the user types in your popup.         */
+     XPLMAvionicsKeyboard_f    keyboardCallback;
+    /* The callback that is called to determine the absolute brightness of the    *
+     * device's screen. Set to NULL to use X-Plane's default behaviour.           */
+     XPLMAvionicsBrightness_f  brightnessCallback;
+    /* A null-terminated string of maximum 64 characters to uniquely identify your*
+     * cockpit device. This must be unique (you cannot re-use an ID that X-Plane  *
+     * or another plugin provides), and it must not contain spaces. This is the   *
+     * string the OBJ file must reference when marking polygons with              *
+     * ATTR_cockpit_device. The string is copied when you call                    *
+     * XPLMCreateAvionicsEx, so you don't need to hold this string in memory after*
+     * the call.                                                                  */
+     char *                    deviceID;
+    /* A null-terminated string to give a user-readable name to your device, which*
+     * can be presented in UI dialogs.                                            */
+     char *                    deviceName;
+    /* A reference which will be passed into your draw and mouse callbacks. Use   *
+     * this to pass information to yourself as needed.                            */
+     void *                    refcon;
+} XPLMCreateAvionics_t;
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMCreateAvionicsEx
+ * 
+ * Creates a new cockpit device to be used in the 3D cockpit. You can call
+ * this at any time: if an aircraft referencing your device is loaded before
+ * your plugin, the simulator will make sure to retroactively map your display
+ * into it.
+ * 
+ *             When you are done with the device, and at least before your
+ *             plugin is unloaded, you should destroy the device using
+ *             XPLMDestroyAvionics().
+ *
+ */
+XPLM_API XPLMAvionicsID XPLMCreateAvionicsEx(
+                         XPLMCreateAvionics_t * inParams);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMDestroyAvionics
+ * 
+ * Destroys the cockpit device and deallocates its screen's memory. You should
+ * only ever call this for devices that you created using
+ * XPLMCreateAvionicsEx(), not X-Plane' built-ine devices you have customised.
+ *
+ */
+XPLM_API void       XPLMDestroyAvionics(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMIsAvionicsBound
+ * 
+ * Returns true (1) if the cockpit device with the given handle is used by the
+ * current aircraft.
+ *
+ */
+XPLM_API int        XPLMIsAvionicsBound(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetAvionicsBrightnessRheo
+ * 
+ * Sets the brightness setting's value, between 0 and 1, for the screen of the
+ * cockpit device with the given handle.
+ * 
+ * If the device is bound to the current aircraft, this is a shortcut to
+ * setting the brightness rheostat value using the
+ * `sim/cockpit2/switches/instrument_brightness_ratio[]` dataref; this sets
+ * the slot in the `instrument_brightness_ratio` array to which the device is
+ * bound.
+ * 
+ * If the device is not currently bound, the device keeps track of its own
+ * screen brightness rheostat, allowing you to control the brightness even
+ * though it isn't connected to the `instrument_brightness_ratio` dataref.
+ *
+ */
+XPLM_API void       XPLMSetAvionicsBrightnessRheo(
+                         XPLMAvionicsID       inHandle,
+                         float                brightness);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetAvionicsBrightnessRheo
+ * 
+ * Returns the brightness setting value, between 0 and 1, for the screen of
+ * the cockpit device with the given handle.
+ * 
+ *         If the device is bound to the current aircraft, this is a shortcut
+ *         to getting the brightness rheostat value from the
+ *         `sim/cockpit2/switches/instrument_brightness_ratio[]` dataref; this
+ *         gets the slot in the `instrument_brightness_ratio` array to which
+ *         the device is bound.
+ * 
+ *         If the device is not currently bound, this returns the device's own
+ *         brightness rheostat value.
+ *
+ */
+XPLM_API float      XPLMGetAvionicsBrightnessRheo(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetAvionicsBusVoltsRatio
+ * 
+ * Returns the ratio of the nominal voltage (1.0 means full nominal voltage)
+ * of the electrical bus to which the given avionics device is bound, or -1 if
+ * the device is not bound to the current aircraft.
+ *
+ */
+XPLM_API float      XPLMGetAvionicsBusVoltsRatio(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMIsCursorOverAvionics
+ * 
+ * Returns true (1) if the mouse is currently over the screen of cockpit
+ * device with the given handle. If they are not NULL, the optional x and y
+ * arguments are filled with the co-ordinates of the mouse cursor in device
+ * co-ordinates.
+ *
+ */
+XPLM_API int        XPLMIsCursorOverAvionics(
+                         XPLMAvionicsID       inHandle,
+                         int *                outX,                   /* Can be NULL */
+                         int *                outY);                  /* Can be NULL */
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMAvionicsNeedsDrawing
+ * 
+ * Tells X-Plane that your device's screen needs to be re-drawn. If your
+ * device is marked for on-demand drawing, X-Plane will call your screen
+ * drawing callback before drawing the next simulator frame. If your device is
+ * already drawn every frame, this has no effect.
+ *
+ */
+XPLM_API void       XPLMAvionicsNeedsDrawing(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetAvionicsPopupVisible
+ * 
+ * Shows or hides the popup window for a cockpit device.
+ *
+ */
+XPLM_API void       XPLMSetAvionicsPopupVisible(
+                         XPLMAvionicsID       inHandle,
+                         int                  inVisible);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMIsAvionicsPopupVisible
+ * 
+ * Returns true (1) if the popup window for a cockpit device is visible.
+ *
+ */
+XPLM_API int        XPLMIsAvionicsPopupVisible(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMPopOutAvionics
+ * 
+ * Pops out the window for a cockpit device.
+ *
+ */
+XPLM_API void       XPLMPopOutAvionics(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMIsAvionicsPoppedOut
+ * 
+ * Returns true (1) if the popup window for a cockpit device is popped out.
+ *
+ */
+XPLM_API int        XPLMIsAvionicsPoppedOut(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMTakeAvionicsKeyboardFocus
+ * 
+ * This routine gives keyboard focus to the popup window of a custom cockpit
+ * device, if it is visible.
+ *
+ */
+XPLM_API void       XPLMTakeAvionicsKeyboardFocus(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMHasAvionicsKeyboardFocus
+ * 
+ * Returns true (1) if the popup window for a cockpit device has keyboard
+ * focus.
+ *
+ */
+XPLM_API int        XPLMHasAvionicsKeyboardFocus(
+                         XPLMAvionicsID       inHandle);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetAvionicsGeometry
+ * 
+ * Returns the bounds of a cockpit device's popup window in the X-Plane
+ * coordinate system.
+ *
+ */
+XPLM_API void       XPLMGetAvionicsGeometry(
+                         XPLMAvionicsID       inHandle,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetAvionicsGeometry
+ * 
+ * Sets the size and position of a cockpit device's popup window in the
+ * X-Plane coordinate system.
+ *
+ */
+XPLM_API void       XPLMSetAvionicsGeometry(
+                         XPLMAvionicsID       inHandle,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetAvionicsGeometryOS
+ * 
+ * Returns the bounds of a cockpit device's popped-out window.
+ *
+ */
+XPLM_API void       XPLMGetAvionicsGeometryOS(
+                         XPLMAvionicsID       inHandle,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetAvionicsGeometryOS
+ * 
+ * Sets the size and position of a cockpit device's popped-out window.
+ *
+ */
+XPLM_API void       XPLMSetAvionicsGeometryOS(
+                         XPLMAvionicsID       inHandle,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+#endif /* XPLM410 */
+
+#endif /* XPLM400 */
+/***************************************************************************
+ * WINDOW API
+ ***************************************************************************/
+/*
+ * The window API provides a high-level abstraction for drawing with UI
+ * interaction.
+ * 
+ * Windows may operate in one of two modes: legacy (for plugins compiled
+ * against old versions of the XPLM, as well as windows created via the
+ * deprecated XPLMCreateWindow() function, rather than XPLMCreateWindowEx()),
+ * or modern (for windows compiled against the XPLM300 or newer API, and
+ * created via XPLMCreateWindowEx()).
+ * 
+ * Modern windows have access to new X-Plane 11 windowing features, like
+ * support for new positioning modes (including being "popped out" into their
+ * own first-class window in the operating system). They can also optionally
+ * be decorated in the style of X-Plane 11 windows (like the map).
+ * 
+ * Modern windows operate in "boxel" units. A boxel ("box of pixels") is a
+ * unit of virtual pixels which, depending on X-Plane's scaling, may
+ * correspond to an arbitrary NxN "box" of real pixels on screen. Because
+ * X-Plane handles this scaling automatically, you can effectively treat the
+ * units as though you were simply drawing in pixels, and know that when
+ * X-Plane is running with 150% or 200% scaling, your drawing will be
+ * automatically scaled (and likewise all mouse coordinates, screen bounds,
+ * etc. will also be auto-scaled).
+ * 
+ * In contrast, legacy windows draw in true screen pixels, and thus tend to
+ * look quite small when X-Plane is operating in a scaled mode.
+ * 
+ * Legacy windows have their origin in the lower left of the main X-Plane
+ * window. In contrast, since modern windows are not constrained to the main
+ * window, they have their origin in the lower left of the entire global
+ * desktop space, and the lower left of the main X-Plane window is not
+ * guaranteed to be (0, 0). In both cases, x increases as you move left, and y
+ * increases as you move up.
+ *
+ */
+
+
+/*
+ * XPLMWindowID
+ * 
+ * This is an opaque identifier for a window.  You use it to control your
+ * window. When you create a window (via either XPLMCreateWindow() or
+ * XPLMCreateWindowEx()), you will specify callbacks to handle drawing, mouse
+ * interaction, etc.
+ *
+ */
+typedef void * XPLMWindowID;
+
+/*
+ * XPLMDrawWindow_f
+ * 
+ * A callback to handle 2-D drawing of your window.  You are passed in your
+ * window and its refcon. Draw the window.  You can use other XPLM functions
+ * from this header to find the current dimensions of your window, etc.  When
+ * this callback is called, the OpenGL context will be set properly for 2-D
+ * window drawing.
+ * 
+ * **Note**: Because you are drawing your window over a background, you can
+ *   make a translucent window easily by simply not filling in your entire
+ *   window's bounds.
+ *
+ */
+typedef void (* XPLMDrawWindow_f)(
+                         XPLMWindowID         inWindowID,
+                         void *               inRefcon);
+
+/*
+ * XPLMHandleKey_f
+ * 
+ * This function is called when a key is pressed or keyboard focus is taken
+ * away from your window.  If losingFocus is 1, you are losing the keyboard
+ * focus, otherwise a key was pressed and inKey contains its character.
+ * 
+ * The window ID passed in will be your window for key presses, or the other
+ * window taking focus  when losing focus. Note that in the modern plugin
+ * system, often focus is taken by the window manager itself; for this resaon,
+ * the window ID may be zero when losing focus, and you should not write code
+ * that depends onit.
+ * 
+ * The refcon passed in will be the one from registration, for both key
+ * presses and losing focus.  
+ * 
+ * Warning: this API declares virtual keys as a signed character; however the
+ * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values
+ * (that is 0x80 instead of -0x80).  So you may need to cast the incoming vkey
+ * to an unsigned char to get correct comparisons in C.
+ *
+ */
+typedef void (* XPLMHandleKey_f)(
+                         XPLMWindowID         inWindowID,
+                         char                 inKey,
+                         XPLMKeyFlags         inFlags,
+                         char                 inVirtualKey,
+                         void *               inRefcon,
+                         int                  losingFocus);
+
+/*
+ * XPLMHandleMouseClick_f
+ * 
+ * You receive this call for one of three events:
+ * 
+ * - when the user clicks the mouse button down
+ * - (optionally) when the user drags the mouse after a down-click, but before
+ *   the up-click
+ * - when the user releases the down-clicked mouse button.
+ * 
+ * You receive the x and y of the click, your window, and a refcon.  Return 1
+ * to consume the click, or 0 to pass it through.
+ * 
+ * WARNING: passing clicks through windows (as of this writing) causes mouse
+ * tracking problems in X-Plane; do not use this feature!
+ * 
+ * The units for x and y values match the units used in your window. Thus, for
+ * "modern" windows (those created via XPLMCreateWindowEx() and compiled
+ * against the XPLM300 library), the units are boxels, while legacy windows
+ * will get pixels. Legacy windows have their origin in the lower left of the
+ * main X-Plane window, while modern windows have their origin in the lower
+ * left of the global desktop space. In both cases, x increases as you move
+ * right, and y increases as you move up.
+ *
+ */
+typedef int (* XPLMHandleMouseClick_f)(
+                         XPLMWindowID         inWindowID,
+                         int                  x,
+                         int                  y,
+                         XPLMMouseStatus      inMouse,
+                         void *               inRefcon);
+
+#if defined(XPLM200)
+/*
+ * XPLMHandleCursor_f
+ * 
+ * The SDK calls your cursor status callback when the mouse is over your
+ * plugin window.  Return a cursor status code to indicate how you would like
+ * X-Plane to manage the cursor.  If you return xplm_CursorDefault, the SDK
+ * will try lower-Z-order plugin windows, then let the sim manage the cursor.
+ * 
+ * Note: you should never show or hide the cursor yourself---these APIs are
+ * typically reference-counted and thus cannot safely and predictably be used
+ * by the SDK.  Instead return one of xplm_CursorHidden to hide the cursor or
+ * xplm_CursorArrow/xplm_CursorCustom to show the cursor.
+ * 
+ * If you want to implement a custom cursor by drawing a cursor in OpenGL, use
+ * xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d
+ * drawing callback (after xplm_Phase_Window is probably a good choice, but
+ * see deprecation warnings on the drawing APIs!).  If you want to use a
+ * custom OS-based cursor, use xplm_CursorCustom to ask X-Plane to show the
+ * cursor but not affect its image.  You can then use an OS specific call like
+ * SetThemeCursor (Mac) or SetCursor/LoadCursor (Windows).
+ * 
+ * The units for x and y values match the units used in your window. Thus, for
+ * "modern" windows (those created via XPLMCreateWindowEx() and compiled
+ * against the XPLM300 library), the units are boxels, while legacy windows
+ * will get pixels. Legacy windows have their origin in the lower left of the
+ * main X-Plane window, while modern windows have their origin in the lower
+ * left of the global desktop space. In both cases, x increases as you move
+ * right, and y increases as you move up.
+ *
+ */
+typedef XPLMCursorStatus (* XPLMHandleCursor_f)(
+                         XPLMWindowID         inWindowID,
+                         int                  x,
+                         int                  y,
+                         void *               inRefcon);
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/*
+ * XPLMHandleMouseWheel_f
+ * 
+ * The SDK calls your mouse wheel callback when one of the mouse wheels is
+ * scrolled within your window.  Return 1 to consume the mouse wheel movement
+ * or 0 to pass them on to a lower window.  (If your window appears opaque to
+ * the user, you should consume mouse wheel scrolling even if it does
+ * nothing.)  The number of "clicks" indicates how far the wheel was turned
+ * since the last callback. The wheel is 0 for the vertical axis or 1 for the
+ * horizontal axis (for OS/mouse combinations that support this).
+ * 
+ * The units for x and y values match the units used in your window. Thus, for
+ * "modern" windows (those created via XPLMCreateWindowEx() and compiled
+ * against the XPLM300 library), the units are boxels, while legacy windows
+ * will get pixels. Legacy windows have their origin in the lower left of the
+ * main X-Plane window, while modern windows have their origin in the lower
+ * left of the global desktop space. In both cases, x increases as you move
+ * right, and y increases as you move up.
+ *
+ */
+typedef int (* XPLMHandleMouseWheel_f)(
+                         XPLMWindowID         inWindowID,
+                         int                  x,
+                         int                  y,
+                         int                  wheel,
+                         int                  clicks,
+                         void *               inRefcon);
+#endif /* XPLM200 */
+
+#if defined(XPLM300)
+/*
+ * XPLMWindowLayer
+ * 
+ * XPLMWindowLayer describes where in the ordering of windows X-Plane should
+ * place a particular window. Windows in higher layers cover windows in lower
+ * layers. So, a given window might be at the top of its particular layer, but
+ * it might still be obscured by a window in a higher layer. (This happens
+ * frequently when floating windows, like X-Plane's map, are covered by a
+ * modal alert.)
+ * 
+ * Your window's layer can only be specified when you create the window (in
+ * the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). For this reason,
+ * layering only applies to windows created with new X-Plane 11 GUI features.
+ * (Windows created using the older XPLMCreateWindow(), or windows compiled
+ * against a pre-XPLM300 version of the SDK will simply be placed in the
+ * flight overlay window layer.)
+ *
+ */
+enum {
+    /* The lowest layer, used for HUD-like displays while flying.                 */
+    xplm_WindowLayerFlightOverlay            = 0,
+
+    /* Windows that "float" over the sim, like the X-Plane 11 map does. If you are*
+     * not sure which layer to create your window in, choose floating.            */
+    xplm_WindowLayerFloatingWindows          = 1,
+
+    /* An interruptive modal that covers the sim with a transparent black overlay *
+     * to draw the user's focus to the alert                                      */
+    xplm_WindowLayerModal                    = 2,
+
+    /* "Growl"-style notifications that are visible in a corner of the screen,    *
+     * even over modals                                                           */
+    xplm_WindowLayerGrowlNotifications       = 3,
+
+
+};
+typedef int XPLMWindowLayer;
+#endif /* XPLM300 */
+
+#if defined(XPLM301)
+/*
+ * XPLMWindowDecoration
+ * 
+ * XPLMWindowDecoration describes how "modern" windows will be displayed. This
+ * impacts both how X-Plane draws your window as well as certain mouse
+ * handlers.
+ * 
+ * Your window's decoration can only be specified when you create the window
+ * (in the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()).
+ *
+ */
+enum {
+    /* X-Plane will draw no decoration for your window, and apply no automatic    *
+     * click handlers. The window will not stop click from passing through its    *
+     * bounds. This is suitable for "windows" which request, say, the full screen *
+     * bounds, then only draw in a small portion of the available area.           */
+    xplm_WindowDecorationNone                = 0,
+
+    /* The default decoration for "native" windows, like the map. Provides a solid*
+     * background, as well as click handlers for resizing and dragging the window.*/
+    xplm_WindowDecorationRoundRectangle      = 1,
+
+    /* X-Plane will draw no decoration for your window, nor will it provide resize*
+     * handlers for your window edges, but it will stop clicks from passing       *
+     * through your windows bounds.                                               */
+    xplm_WindowDecorationSelfDecorated       = 2,
+
+    /* Like self-decorated, but with resizing; X-Plane will draw no decoration for*
+     * your window, but it will stop clicks from passing through your windows     *
+     * bounds, and provide automatic mouse handlers for resizing.                 */
+    xplm_WindowDecorationSelfDecoratedResizable = 3,
+
+
+};
+typedef int XPLMWindowDecoration;
+#endif /* XPLM301 */
+
+#if defined(XPLM200)
+/*
+ * XPLMCreateWindow_t
+ * 
+ * The XPMCreateWindow_t structure defines all of the parameters used to
+ * create a modern window using XPLMCreateWindowEx().  The structure will be
+ * expanded in future SDK APIs to include more features.  Always set the
+ * structSize member to the size of your struct in bytes!
+ * 
+ * All windows created by this function in the XPLM300 version of the API are
+ * created with the new X-Plane 11 GUI features. This means your plugin will
+ * get to "know" about the existence of X-Plane windows other than the main
+ * window. All drawing and mouse callbacks for your window will occur in
+ * "boxels," giving your windows automatic support for high-DPI scaling in
+ * X-Plane. In addition, your windows can opt-in to decoration with the
+ * X-Plane 11 window styling, and you can use the
+ * XPLMSetWindowPositioningMode() API to make your window "popped out" into a
+ * first-class operating system window.
+ * 
+ * Note that this requires dealing with your window's bounds in "global
+ * desktop" positioning units, rather than the traditional panel coordinate
+ * system. In global desktop coordinates, the main X-Plane window may not have
+ * its origin at coordinate (0, 0), and your own window may have negative
+ * coordinates. Assuming you don't implicitly assume (0, 0) as your origin,
+ * the only API change you should need is to start using
+ * XPLMGetMouseLocationGlobal() rather than XPLMGetMouseLocation(), and
+ * XPLMGetScreenBoundsGlobal() instead of XPLMGetScreenSize().
+ * 
+ * If you ask to be decorated as a floating window, you'll get the blue window
+ * control bar and blue backing that you see in X-Plane 11's normal "floating"
+ * windows (like the map).
+ *
+ */
+typedef struct {
+    /* Used to inform XPLMCreateWindowEx() of the SDK version you compiled        *
+     * against; should always be set to sizeof(XPLMCreateWindow_t)                */
+     int                       structSize;
+    /* Left bound, in global desktop boxels                                       */
+     int                       left;
+    /* Top bound, in global desktop boxels                                        */
+     int                       top;
+    /* Right bound, in global desktop boxels                                      */
+     int                       right;
+    /* Bottom bound, in global desktop boxels                                     */
+     int                       bottom;
+     int                       visible;
+     XPLMDrawWindow_f          drawWindowFunc;
+    /* A callback to handle the user left-clicking within your window (or NULL to *
+     * ignore left clicks)                                                        */
+     XPLMHandleMouseClick_f    handleMouseClickFunc;
+     XPLMHandleKey_f           handleKeyFunc;
+     XPLMHandleCursor_f        handleCursorFunc;
+     XPLMHandleMouseWheel_f    handleMouseWheelFunc;
+    /* A reference which will be passed into each of your window callbacks. Use   *
+     * this to pass information to yourself as needed.                            */
+     void *                    refcon;
+#if defined(XPLM301)
+    /* Specifies the type of X-Plane 11-style "wrapper" you want around your      *
+     * window, if any                                                             */
+     XPLMWindowDecoration      decorateAsFloatingWindow;
+#endif /* XPLM301 */
+#if defined(XPLM300)
+     XPLMWindowLayer           layer;
+#endif /* XPLM300 */
+#if defined(XPLM300)
+    /* A callback to handle the user right-clicking within your window (or NULL to*
+     * ignore right clicks)                                                       */
+     XPLMHandleMouseClick_f    handleRightClickFunc;
+#endif /* XPLM300 */
+} XPLMCreateWindow_t;
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/*
+ * XPLMCreateWindowEx
+ * 
+ * This routine creates a new "modern" window. You pass in an
+ * XPLMCreateWindow_t structure with all of the fields set in.  You must set
+ * the structSize of the structure to the size of the actual structure you
+ * used.  Also, you must provide functions for every callback---you may not
+ * leave them null!  (If you do not support the cursor or mouse wheel, use
+ * functions that return the default values.)
+ *
+ */
+XPLM_API XPLMWindowID XPLMCreateWindowEx(
+                         XPLMCreateWindow_t * inParams);
+#endif /* XPLM200 */
+
+/*
+ * XPLMCreateWindow
+ * 
+ * Deprecated as of XPLM300.
+ * 
+ * This routine creates a new legacy window. Unlike modern windows (created
+ * via XPLMCreateWindowEx()), legacy windows do not have access to X-Plane 11
+ * features like automatic scaling for high-DPI screens, native window styles,
+ * or support for being "popped out" into first-class operating system
+ * windows.
+ * 
+ * Pass in the dimensions and offsets to the window's bottom left corner from
+ * the bottom left of the screen.  You can specify whether the window is
+ * initially visible or not.  Also, you pass in three callbacks to run the
+ * window and a refcon.  This function returns a window ID you can use to
+ * refer to the new window.
+ * 
+ * NOTE: Legacy windows do not have "frames"; you are responsible for drawing
+ * the background and frame of the window.  Higher level libraries have
+ * routines which make this easy.
+ *
+ */
+XPLM_API XPLMWindowID XPLMCreateWindow(
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom,
+                         int                  inIsVisible,
+                         XPLMDrawWindow_f     inDrawCallback,
+                         XPLMHandleKey_f      inKeyCallback,
+                         XPLMHandleMouseClick_f inMouseCallback,
+                         void *               inRefcon);
+
+/*
+ * XPLMDestroyWindow
+ * 
+ * This routine destroys a window.  The window's callbacks are not called
+ * after this call. Keyboard focus is removed from the window before
+ * destroying it.
+ *
+ */
+XPLM_API void       XPLMDestroyWindow(
+                         XPLMWindowID         inWindowID);
+
+/*
+ * XPLMGetScreenSize
+ * 
+ * This routine returns the size of the main X-Plane OpenGL window in pixels.
+ * This number can be used to get a rough idea of the amount of detail the
+ * user will be able to see when drawing in 3-d.
+ *
+ */
+XPLM_API void       XPLMGetScreenSize(
+                         int *                outWidth,               /* Can be NULL */
+                         int *                outHeight);             /* Can be NULL */
+
+#if defined(XPLM300)
+/*
+ * XPLMGetScreenBoundsGlobal
+ * 
+ * This routine returns the bounds of the "global" X-Plane desktop, in boxels.
+ * Unlike the non-global version XPLMGetScreenSize(), this is multi-monitor
+ * aware. There are three primary consequences of multimonitor awareness.
+ * 
+ * First, if the user is running X-Plane in full-screen on two or more
+ * monitors (typically configured using one full-screen window per monitor),
+ * the global desktop will be sized to include all X-Plane windows.
+ * 
+ * Second, the origin of the screen coordinates is not guaranteed to be (0,
+ * 0). Suppose the user has two displays side-by-side, both running at 1080p.
+ * Suppose further that they've configured their OS to make the left display
+ * their "primary" monitor, and that X-Plane is running in full-screen on
+ * their right monitor only. In this case, the global desktop bounds would be
+ * the rectangle from (1920, 0) to (3840, 1080). If the user later asked
+ * X-Plane to draw on their primary monitor as well, the bounds would change
+ * to (0, 0) to (3840, 1080).
+ * 
+ * Finally, if the usable area of the virtual desktop is not a perfect
+ * rectangle (for instance, because the monitors have different resolutions or
+ * because one monitor is configured in the operating system to be above and
+ * to the right of the other), the global desktop will include any wasted
+ * space. Thus, if you have two 1080p monitors, and monitor 2 is configured to
+ * have its bottom left touch monitor 1's upper right, your global desktop
+ * area would be the rectangle from (0, 0) to (3840, 2160).
+ * 
+ * Note that popped-out windows (windows drawn in their own operating system
+ * windows, rather than "floating" within X-Plane) are not included in these
+ * bounds.
+ *
+ */
+XPLM_API void       XPLMGetScreenBoundsGlobal(
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMReceiveMonitorBoundsGlobal_f
+ * 
+ * This function is informed of the global bounds (in boxels) of a particular
+ * monitor within the X-Plane global desktop space. Note that X-Plane must be
+ * running in full screen on a monitor in order for that monitor to be passed
+ * to you in this callback.
+ *
+ */
+typedef void (* XPLMReceiveMonitorBoundsGlobal_f)(
+                         int                  inMonitorIndex,
+                         int                  inLeftBx,
+                         int                  inTopBx,
+                         int                  inRightBx,
+                         int                  inBottomBx,
+                         void *               inRefcon);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMGetAllMonitorBoundsGlobal
+ * 
+ * This routine immediately calls you back with the bounds (in boxels) of each
+ * full-screen X-Plane window within the X-Plane global desktop space. Note
+ * that if a monitor is *not* covered by an X-Plane window, you cannot get its
+ * bounds this way. Likewise, monitors with only an X-Plane window (not in
+ * full-screen mode) will not be included.
+ * 
+ * If X-Plane is running in full-screen and your monitors are of the same size
+ * and configured contiguously in the OS, then the combined global bounds of
+ * all full-screen monitors will match the total global desktop bounds, as
+ * returned by XPLMGetScreenBoundsGlobal(). (Of course, if X-Plane is running
+ * in windowed mode, this will not be the case. Likewise, if you have
+ * differently sized monitors, the global desktop space will include wasted
+ * space.)
+ * 
+ * Note that this function's monitor indices match those provided by
+ * XPLMGetAllMonitorBoundsOS(), but the coordinates are different (since the
+ * X-Plane global desktop may not match the operating system's global desktop,
+ * and one X-Plane boxel may be larger than one pixel due to 150% or 200%
+ * scaling).
+ *
+ */
+XPLM_API void       XPLMGetAllMonitorBoundsGlobal(
+                         XPLMReceiveMonitorBoundsGlobal_f inMonitorBoundsCallback,
+                         void *               inRefcon);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMReceiveMonitorBoundsOS_f
+ * 
+ * This function is informed of the global bounds (in pixels) of a particular
+ * monitor within the operating system's global desktop space. Note that a
+ * monitor index being passed to you here does not indicate that X-Plane is
+ * running in full screen on this monitor, or even that any X-Plane windows
+ * exist on this monitor.
+ *
+ */
+typedef void (* XPLMReceiveMonitorBoundsOS_f)(
+                         int                  inMonitorIndex,
+                         int                  inLeftPx,
+                         int                  inTopPx,
+                         int                  inRightPx,
+                         int                  inBottomPx,
+                         void *               inRefcon);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMGetAllMonitorBoundsOS
+ * 
+ * This routine immediately calls you back with the bounds (in pixels) of each
+ * monitor within the operating system's global desktop space. Note that
+ * unlike XPLMGetAllMonitorBoundsGlobal(), this may include monitors that have
+ * no X-Plane window on them.
+ * 
+ * Note that this function's monitor indices match those provided by
+ * XPLMGetAllMonitorBoundsGlobal(), but the coordinates are different (since
+ * the X-Plane global desktop may not match the operating system's global
+ * desktop, and one X-Plane boxel may be larger than one pixel).
+ *
+ */
+XPLM_API void       XPLMGetAllMonitorBoundsOS(
+                         XPLMReceiveMonitorBoundsOS_f inMonitorBoundsCallback,
+                         void *               inRefcon);
+#endif /* XPLM300 */
+
+/*
+ * XPLMGetMouseLocation
+ * 
+ * Deprecated in XPLM300. Modern windows should use
+ * XPLMGetMouseLocationGlobal() instead.
+ * 
+ * This routine returns the current mouse location in pixels relative to the
+ * main X-Plane window. The bottom left corner of the main window is (0, 0). 
+ * Pass NULL to not receive info about either parameter.
+ * 
+ * Because this function gives the mouse position relative to the main X-Plane
+ * window (rather than in global bounds), this function should only be used by
+ * legacy windows. Modern windows should instead get the mouse position in
+ * global desktop coordinates using XPLMGetMouseLocationGlobal().
+ * 
+ * Note that unlike XPLMGetMouseLocationGlobal(), if the mouse goes outside
+ * the user's main monitor (for instance, to a pop out window or a secondary
+ * monitor), this function will not reflect it.
+ *
+ */
+XPLM_API void       XPLMGetMouseLocation(
+                         int *                outX,                   /* Can be NULL */
+                         int *                outY);                  /* Can be NULL */
+
+#if defined(XPLM300)
+/*
+ * XPLMGetMouseLocationGlobal
+ * 
+ * Returns the current mouse location in global desktop boxels. Unlike
+ * XPLMGetMouseLocation(), the bottom left of the main X-Plane window is not
+ * guaranteed to be (0, 0)---instead, the origin is the lower left of the
+ * entire global desktop space. In addition, this routine gives the real mouse
+ * location when the mouse goes to X-Plane windows other than the primary
+ * display. Thus, it can be used with both pop-out windows and secondary
+ * monitors.
+ * 
+ * This is the mouse location function to use with modern windows (i.e., those
+ * created by XPLMCreateWindowEx()).
+ * 
+ * Pass NULL to not receive info about either parameter.
+ *
+ */
+XPLM_API void       XPLMGetMouseLocationGlobal(
+                         int *                outX,                   /* Can be NULL */
+                         int *                outY);                  /* Can be NULL */
+#endif /* XPLM300 */
+
+/*
+ * XPLMGetWindowGeometry
+ * 
+ * This routine returns the position and size of a window. The units and
+ * coordinate system vary depending on the type of window you have.
+ * 
+ * If this is a legacy window (one compiled against a pre-XPLM300 version of
+ * the SDK, or an XPLM300 window that was not created using
+ * XPLMCreateWindowEx()), the units are pixels relative to the main X-Plane
+ * display.
+ * 
+ * If, on the other hand, this is a new X-Plane 11-style window (compiled
+ * against the XPLM300 SDK and created using XPLMCreateWindowEx()), the units
+ * are global desktop boxels.
+ * 
+ * Pass NULL to not receive any paramter.
+ *
+ */
+XPLM_API void       XPLMGetWindowGeometry(
+                         XPLMWindowID         inWindowID,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+
+/*
+ * XPLMSetWindowGeometry
+ * 
+ * This routine allows you to set the position and size of a window.
+ * 
+ * The units and coordinate system match those of XPLMGetWindowGeometry().
+ * That is, modern windows use global desktop boxel coordinates, while legacy
+ * windows use pixels relative to the main X-Plane display.
+ * 
+ * Note that this only applies to "floating" windows (that is, windows that
+ * are drawn within the X-Plane simulation windows, rather than being "popped
+ * out" into their own first-class operating system windows). To set the
+ * position of windows whose positioning mode is xplm_WindowPopOut, you'll
+ * need to instead use XPLMSetWindowGeometryOS().
+ *
+ */
+XPLM_API void       XPLMSetWindowGeometry(
+                         XPLMWindowID         inWindowID,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+
+#if defined(XPLM300)
+/*
+ * XPLMGetWindowGeometryOS
+ * 
+ * This routine returns the position and size of a "popped out" window (i.e.,
+ * a window whose positioning mode is xplm_WindowPopOut), in operating system
+ * pixels.  Pass NULL to not receive any parameter.
+ *
+ */
+XPLM_API void       XPLMGetWindowGeometryOS(
+                         XPLMWindowID         inWindowID,
+                         int *                outLeft,                /* Can be NULL */
+                         int *                outTop,                 /* Can be NULL */
+                         int *                outRight,               /* Can be NULL */
+                         int *                outBottom);             /* Can be NULL */
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMSetWindowGeometryOS
+ * 
+ * This routine allows you to set the position and size, in operating system
+ * pixel coordinates, of a popped out window (that is, a window whose
+ * positioning mode is xplm_WindowPopOut, which exists outside the X-Plane
+ * simulation window, in its own first-class operating system window).
+ * 
+ * Note that you are responsible for ensuring both that your window is popped
+ * out (using XPLMWindowIsPoppedOut()) and that a monitor really exists at the
+ * OS coordinates you provide (using XPLMGetAllMonitorBoundsOS()).
+ *
+ */
+XPLM_API void       XPLMSetWindowGeometryOS(
+                         XPLMWindowID         inWindowID,
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+#endif /* XPLM300 */
+
+#if defined(XPLM301)
+/*
+ * XPLMGetWindowGeometryVR
+ * 
+ * Returns the width and height, in boxels, of a window in VR. Note that you
+ * are responsible for ensuring your window is in VR (using
+ * XPLMWindowIsInVR()).
+ *
+ */
+XPLM_API void       XPLMGetWindowGeometryVR(
+                         XPLMWindowID         inWindowID,
+                         int *                outWidthBoxels,         /* Can be NULL */
+                         int *                outHeightBoxels);       /* Can be NULL */
+#endif /* XPLM301 */
+
+#if defined(XPLM301)
+/*
+ * XPLMSetWindowGeometryVR
+ * 
+ * This routine allows you to set the size, in boxels, of a window in VR (that
+ * is, a window whose positioning mode is xplm_WindowVR).
+ * 
+ * Note that you are responsible for ensuring your window is in VR (using
+ * XPLMWindowIsInVR()).
+ *
+ */
+XPLM_API void       XPLMSetWindowGeometryVR(
+                         XPLMWindowID         inWindowID,
+                         int                  widthBoxels,
+                         int                  heightBoxels);
+#endif /* XPLM301 */
+
+/*
+ * XPLMGetWindowIsVisible
+ * 
+ * Returns true (1) if the specified window is visible.
+ *
+ */
+XPLM_API int        XPLMGetWindowIsVisible(
+                         XPLMWindowID         inWindowID);
+
+/*
+ * XPLMSetWindowIsVisible
+ * 
+ * This routine shows or hides a window.
+ *
+ */
+XPLM_API void       XPLMSetWindowIsVisible(
+                         XPLMWindowID         inWindowID,
+                         int                  inIsVisible);
+
+#if defined(XPLM300)
+/*
+ * XPLMWindowIsPoppedOut
+ * 
+ * True if this window has been popped out (making it a first-class window in
+ * the operating system), which in turn is true if and only if you have set
+ * the window's positioning mode to xplm_WindowPopOut.
+ * 
+ * Only applies to modern windows. (Windows created using the deprecated
+ * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+ * the SDK cannot be popped out.)
+ *
+ */
+XPLM_API int        XPLMWindowIsPoppedOut(
+                         XPLMWindowID         inWindowID);
+#endif /* XPLM300 */
+
+#if defined(XPLM301)
+/*
+ * XPLMWindowIsInVR
+ * 
+ * True if this window has been moved to the virtual reality (VR) headset,
+ * which in turn is true if and only if you have set the window's positioning
+ * mode to xplm_WindowVR.
+ * 
+ * Only applies to modern windows. (Windows created using the deprecated
+ * XPLMCreateWindow(), or windows compiled against a pre-XPLM301 version of
+ * the SDK cannot be moved to VR.)
+ *
+ */
+XPLM_API int        XPLMWindowIsInVR(
+                         XPLMWindowID         inWindowID);
+#endif /* XPLM301 */
+
+#if defined(XPLM300)
+/*
+ * XPLMSetWindowGravity
+ * 
+ * A window's "gravity" controls how the window shifts as the whole X-Plane
+ * window resizes. A gravity of 1 means the window maintains its positioning
+ * relative to the right or top edges, 0 the left/bottom, and 0.5 keeps it
+ * centered.
+ * 
+ * Default gravity is (0, 1, 0, 1), meaning your window will maintain its
+ * position relative to the top left and will not change size as its
+ * containing window grows.
+ * 
+ * If you wanted, say, a window that sticks to the top of the screen (with a
+ * constant height), but which grows to take the full width of the window, you
+ * would pass (0, 1, 1, 1). Because your left and right edges would maintain
+ * their positioning relative to their respective edges of the screen, the
+ * whole width of your window would change with the X-Plane window.
+ * 
+ * Only applies to modern windows. (Windows created using the deprecated
+ * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+ * the SDK will simply get the default gravity.)
+ *
+ */
+XPLM_API void       XPLMSetWindowGravity(
+                         XPLMWindowID         inWindowID,
+                         float                inLeftGravity,
+                         float                inTopGravity,
+                         float                inRightGravity,
+                         float                inBottomGravity);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMSetWindowResizingLimits
+ * 
+ * Sets the minimum and maximum size of the client rectangle of the given
+ * window. (That is, it does not include any window styling that you might
+ * have asked X-Plane to apply on your behalf.) All resizing operations are
+ * constrained to these sizes.
+ * 
+ * Only applies to modern windows. (Windows created using the deprecated
+ * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+ * the SDK will have no minimum or maximum size.)
+ *
+ */
+XPLM_API void       XPLMSetWindowResizingLimits(
+                         XPLMWindowID         inWindowID,
+                         int                  inMinWidthBoxels,
+                         int                  inMinHeightBoxels,
+                         int                  inMaxWidthBoxels,
+                         int                  inMaxHeightBoxels);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMWindowPositioningMode
+ * 
+ * XPLMWindowPositionMode describes how X-Plane will position your window on
+ * the user's screen. X-Plane will maintain this positioning mode even as the
+ * user resizes their window or adds/removes full-screen monitors.
+ * 
+ * Positioning mode can only be set for "modern" windows (that is, windows
+ * created using XPLMCreateWindowEx() and compiled against the XPLM300 SDK).
+ * Windows created using the deprecated XPLMCreateWindow(), or windows
+ * compiled against a pre-XPLM300 version of the SDK will simply get the
+ * "free" positioning mode.
+ *
+ */
+enum {
+    /* The default positioning mode. Set the window geometry and its future       *
+     * position will be determined by its window gravity, resizing limits, and    *
+     * user interactions.                                                         */
+    xplm_WindowPositionFree                  = 0,
+
+    /* Keep the window centered on the monitor you specify                        */
+    xplm_WindowCenterOnMonitor               = 1,
+
+    /* Keep the window full screen on the monitor you specify                     */
+    xplm_WindowFullScreenOnMonitor           = 2,
+
+    /* Like gui_window_full_screen_on_monitor, but stretches over *all* monitors  *
+     * and popout windows. This is an obscure one... unless you have a very good  *
+     * reason to need it, you probably don't!                                     */
+    xplm_WindowFullScreenOnAllMonitors       = 3,
+
+    /* A first-class window in the operating system, completely separate from the *
+     * X-Plane window(s)                                                          */
+    xplm_WindowPopOut                        = 4,
+
+#if defined(XPLM301)
+    /* A floating window visible on the VR headset                                */
+    xplm_WindowVR                            = 5,
+
+#endif /* XPLM301 */
+
+};
+typedef int XPLMWindowPositioningMode;
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMSetWindowPositioningMode
+ * 
+ * Sets the policy for how X-Plane will position your window.
+ * 
+ * Some positioning modes apply to a particular monitor. For those modes, you
+ * can pass a negative monitor index to position the window on the main
+ * X-Plane monitor (the screen with the X-Plane menu bar at the top). Or, if
+ * you have a specific monitor you want to position your window on, you can
+ * pass a real monitor index as received from, e.g.,
+ * XPLMGetAllMonitorBoundsOS().
+ * 
+ * Only applies to modern windows. (Windows created using the deprecated
+ * XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+ * the SDK will always use xplm_WindowPositionFree.)
+ *
+ */
+XPLM_API void       XPLMSetWindowPositioningMode(
+                         XPLMWindowID         inWindowID,
+                         XPLMWindowPositioningMode inPositioningMode,
+                         int                  inMonitorIndex);
+#endif /* XPLM300 */
+
+#if defined(XPLM300)
+/*
+ * XPLMSetWindowTitle
+ * 
+ * Sets the name for a window. This only applies to windows that opted-in to
+ * styling as an X-Plane 11 floating window (i.e., with styling mode
+ * xplm_WindowDecorationRoundRectangle) when they were created using
+ * XPLMCreateWindowEx().
+ *
+ */
+XPLM_API void       XPLMSetWindowTitle(
+                         XPLMWindowID         inWindowID,
+                         const char *         inWindowTitle);
+#endif /* XPLM300 */
+
+/*
+ * XPLMGetWindowRefCon
+ * 
+ * Returns a window's reference constant, the unique value you can use for
+ * your own purposes.
+ *
+ */
+XPLM_API void *     XPLMGetWindowRefCon(
+                         XPLMWindowID         inWindowID);
+
+/*
+ * XPLMSetWindowRefCon
+ * 
+ * Sets a window's reference constant.  Use this to pass data to yourself in
+ * the callbacks.
+ *
+ */
+XPLM_API void       XPLMSetWindowRefCon(
+                         XPLMWindowID         inWindowID,
+                         void *               inRefcon);
+
+/*
+ * XPLMTakeKeyboardFocus
+ * 
+ * This routine gives a specific window keyboard focus.  Keystrokes will be
+ * sent to that window.  Pass a window ID of 0 to remove keyboard focus from
+ * any plugin-created windows and instead pass keyboard strokes directly to
+ * X-Plane.
+ *
+ */
+XPLM_API void       XPLMTakeKeyboardFocus(
+                         XPLMWindowID         inWindow);
+
+/*
+ * XPLMHasKeyboardFocus
+ * 
+ * Returns true (1) if the indicated window has keyboard focus. Pass a window
+ * ID of 0 to see if no plugin window has focus, and all keystrokes will go
+ * directly to X-Plane.
+ *
+ */
+XPLM_API int        XPLMHasKeyboardFocus(
+                         XPLMWindowID         inWindow);
+
+/*
+ * XPLMBringWindowToFront
+ * 
+ * This routine brings the window to the front of the Z-order for its layer. 
+ * Windows are brought to the front automatically when they are created.
+ * Beyond that, you should make sure you are front before handling mouse
+ * clicks.
+ * 
+ * Note that this only brings your window to the front of its layer
+ * (XPLMWindowLayer). Thus, if you have a window in the floating window layer
+ * (xplm_WindowLayerFloatingWindows), but there is a modal window (in layer
+ * xplm_WindowLayerModal) above you, you would still not be the true frontmost
+ * window after calling this. (After all, the window layers are strictly
+ * ordered, and no window in a lower layer can ever be above any window in a
+ * higher one.)
+ *
+ */
+XPLM_API void       XPLMBringWindowToFront(
+                         XPLMWindowID         inWindow);
+
+/*
+ * XPLMIsWindowInFront
+ * 
+ * This routine returns true if the window you passed in is the frontmost
+ * visible window in its layer (XPLMWindowLayer).
+ * 
+ * Thus, if you have a window at the front of the floating window layer
+ * (xplm_WindowLayerFloatingWindows), this will return true even if there is a
+ * modal window (in layer xplm_WindowLayerModal) above you. (Not to worry,
+ * though: in such a case, X-Plane will not pass clicks or keyboard input down
+ * to your layer until the window above stops "eating" the input.)
+ * 
+ * Note that legacy windows are always placed in layer
+ * xplm_WindowLayerFlightOverlay, while modern-style windows default to
+ * xplm_WindowLayerFloatingWindows. This means it's perfectly consistent to
+ * have two different plugin-created windows (one legacy, one modern) *both*
+ * be in the front (of their different layers!) at the same time.
+ *
+ */
+XPLM_API int        XPLMIsWindowInFront(
+                         XPLMWindowID         inWindow);
+
+/***************************************************************************
+ * KEY SNIFFERS
+ ***************************************************************************/
+/*
+ * Low-level keyboard handlers. Allows for intercepting keystrokes outside the
+ * normal rules of the user interface.
+ *
+ */
+
+
+/*
+ * XPLMKeySniffer_f
+ * 
+ * This is the prototype for a low level key-sniffing function.  Window-based
+ * UI _should not use this_!  The windowing system provides high-level
+ * mediated keyboard access, via the callbacks you attach to your
+ * XPLMCreateWindow_t. By comparison, the key sniffer provides low level
+ * keyboard access.
+ * 
+ * Key sniffers are provided to allow libraries to provide non-windowed user
+ * interaction.  For example, the MUI library uses a key sniffer to do pop-up
+ * text entry.
+ * 
+ * Return 1 to pass the key on to the next sniffer, the window manager,
+ * X-Plane, or whomever is down stream.  Return 0 to consume the key.
+ * 
+ * Warning: this API declares virtual keys as a signed character; however the
+ * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values
+ * (that is 0x80 instead of -0x80).  So you may need to cast the incoming vkey
+ * to an unsigned char to get correct comparisons in C.
+ *
+ */
+typedef int (* XPLMKeySniffer_f)(
+                         char                 inChar,
+                         XPLMKeyFlags         inFlags,
+                         char                 inVirtualKey,
+                         void *               inRefcon);
+
+/*
+ * XPLMRegisterKeySniffer
+ * 
+ * This routine registers a key sniffing callback.  You specify whether you
+ * want to sniff before the window system, or only sniff keys the window
+ * system does not consume.  You should ALMOST ALWAYS sniff non-control keys
+ * after the window system.  When the window system consumes a key, it is
+ * because the user has "focused" a window.  Consuming the key or taking
+ * action based on the key will produce very weird results.  Returns
+ * 1 if successful.
+ *
+ */
+XPLM_API int        XPLMRegisterKeySniffer(
+                         XPLMKeySniffer_f     inCallback,
+                         int                  inBeforeWindows,
+                         void *               inRefcon);
+
+/*
+ * XPLMUnregisterKeySniffer
+ * 
+ * This routine unregisters a key sniffer.  You must unregister a key sniffer
+ * for every time you register one with the exact same signature.  Returns 1
+ * if successful.
+ *
+ */
+XPLM_API int        XPLMUnregisterKeySniffer(
+                         XPLMKeySniffer_f     inCallback,
+                         int                  inBeforeWindows,
+                         void *               inRefcon);
+
+/***************************************************************************
+ * HOT KEYS
+ ***************************************************************************/
+/*
+ * Keystrokes that can be managed by others. These are lower-level than window
+ * keyboard handlers (i.e., callbacks you attach to your XPLMCreateWindow_t),
+ * but higher level than key sniffers.
+ *
+ */
+
+
+/*
+ * XPLMHotKey_f
+ * 
+ * Your hot key callback simply takes a pointer of your choosing.
+ *
+ */
+typedef void (* XPLMHotKey_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMHotKeyID
+ * 
+ * An opaque ID used to identify a hot key.
+ *
+ */
+typedef void * XPLMHotKeyID;
+
+/*
+ * XPLMRegisterHotKey
+ * 
+ * This routine registers a hot key.  You specify your preferred key stroke
+ * virtual key/flag combination, a description of what your callback does (so
+ * other plug-ins can describe the plug-in to the user for remapping) and a
+ * callback function and opaque pointer to pass in).  A new hot key ID is
+ * returned.  During execution, the actual key associated with your hot key
+ * may change, but you are insulated from this.
+ *
+ */
+XPLM_API XPLMHotKeyID XPLMRegisterHotKey(
+                         char                 inVirtualKey,
+                         XPLMKeyFlags         inFlags,
+                         const char *         inDescription,
+                         XPLMHotKey_f         inCallback,
+                         void *               inRefcon);
+
+/*
+ * XPLMUnregisterHotKey
+ * 
+ * Unregisters a hot key.  You can only unregister your own hot keys.
+ *
+ */
+XPLM_API void       XPLMUnregisterHotKey(
+                         XPLMHotKeyID         inHotKey);
+
+/*
+ * XPLMCountHotKeys
+ * 
+ * Returns the number of current hot keys.
+ *
+ */
+XPLM_API int        XPLMCountHotKeys(void);
+
+/*
+ * XPLMGetNthHotKey
+ * 
+ * Returns a hot key by index, for iteration on all hot keys.
+ *
+ */
+XPLM_API XPLMHotKeyID XPLMGetNthHotKey(
+                         int                  inIndex);
+
+/*
+ * XPLMGetHotKeyInfo
+ * 
+ * Returns information about the hot key.  Return NULL for any parameter you
+ * don't want info about.  The description should be at least 512 chars long.
+ *
+ */
+XPLM_API void       XPLMGetHotKeyInfo(
+                         XPLMHotKeyID         inHotKey,
+                         char *               outVirtualKey,          /* Can be NULL */
+                         XPLMKeyFlags *       outFlags,               /* Can be NULL */
+                         char *               outDescription,         /* Can be NULL */
+                         XPLMPluginID *       outPlugin);             /* Can be NULL */
+
+/*
+ * XPLMSetHotKeyCombination
+ * 
+ * Remaps a hot key's keystrokes.  You may remap another plugin's keystrokes.
+ *
+ */
+XPLM_API void       XPLMSetHotKeyCombination(
+                         XPLMHotKeyID         inHotKey,
+                         char                 inVirtualKey,
+                         XPLMKeyFlags         inFlags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMGraphics.h b/SDK/CHeaders/XPLM/XPLMGraphics.h
new file mode 100644
index 0000000..f05cb1c
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMGraphics.h
@@ -0,0 +1,437 @@
+#ifndef _XPLMGraphics_h_
+#define _XPLMGraphics_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMGraphics
+ ***************************************************************************/
+/*
+ * A few notes on coordinate systems:
+ * 
+ * X-Plane uses three kinds of coordinates.  Global coordinates are specified
+ * as latitude, longitude and elevation.  This coordinate system never changes
+ * but is not very precise.
+ * 
+ * OpenGL (or 'local') coordinates are cartesian and move with the aircraft. 
+ * They offer more precision and are used for 3-d OpenGL drawing.  The X axis
+ * is aligned east-west with positive X meaning east.  The Y axis is aligned
+ * straight up and down at the point 0,0,0 (but since the Earth is round it is
+ * not truly straight up and down at other points).  The Z axis is aligned
+ * north-south at 0, 0, 0 with positive Z pointing south (but since the Earth
+ * is round it isn't exactly north-south as you move east or west of 0, 0, 0).
+ * One unit is one meter and the point 0,0,0 is on the surface of the Earth at
+ * sea level for some latitude and longitude picked by the sim such that the
+ * user's aircraft is reasonably nearby.
+ * 
+ * 2-d Panel coordinates are 2d, with the X axis horizontal and the Y axis
+ *   vertical. The point 0,0 is the bottom left and 1024,768 is the upper
+ *   right of the screen. This is true no matter what resolution the user's
+ *   monitor is in; when running in higher resolution, graphics will be
+ *   scaled.
+ * 
+ * Use X-Plane's routines to convert between global and local coordinates.  Do
+ * not attempt to do this conversion yourself; the precise 'roundness' of
+ * X-Plane's physics model may not match your own, and (to make things
+ * weirder) the user can potentially customize the physics of the current
+ * planet.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * X-PLANE GRAPHICS
+ ***************************************************************************/
+/*
+ * These routines allow you to use OpenGL with X-Plane.
+ *
+ */
+
+
+/*
+ * XPLMTextureID
+ * 
+ * XPLM Texture IDs name well-known textures in the sim for you to use. This
+ * allows you to recycle textures from X-Plane, saving VRAM.
+ * 
+ * *Warning*: do not use these enums.  The only remaining use they have is to
+ *  access the legacy compatibility v10 UI texture; if you need this, get it
+ *  via the Widgets library.
+ *
+ */
+enum {
+    /* The bitmap that contains window outlines, button outlines, fonts, etc.     */
+    xplm_Tex_GeneralInterface                = 0,
+
+#if defined(XPLM_DEPRECATED)
+    /* The exterior paint for the user's aircraft (daytime).                      */
+    xplm_Tex_AircraftPaint                   = 1,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* The exterior light map for the user's aircraft.                            */
+    xplm_Tex_AircraftLiteMap                 = 2,
+
+#endif /* XPLM_DEPRECATED */
+
+};
+typedef int XPLMTextureID;
+
+/*
+ * XPLMSetGraphicsState
+ * 
+ * XPLMSetGraphicsState changes OpenGL's fixed function pipeline state.  You
+ * are not responsible for restoring any state that is accessed via
+ * XPLMSetGraphicsState, but you are responsible for not accessing this state
+ * directly.
+ * 
+ * - inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG);
+ * - inNumberTexUnits - enables or disables a number of multitexturing units.
+ *   If the number is 0, 2d texturing is disabled entirely, as in
+ *   glDisable(GL_TEXTURE_2D);  Otherwise, 2d texturing is enabled, and a
+ *   number of multitexturing units are enabled sequentially, starting with
+ *   unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable
+ *   (GL_TEXTURE_2D);
+ * - inEnableLighting - enables or disables OpenGL lighting, e.g.
+ *   glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
+ * - inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g.
+ *   glEnable(GL_ALPHA_TEST);
+ * - inEnableAlphaBlending - enables or disables alpha blending per pixel,
+ *   e.g. glEnable(GL_BLEND);
+ * - inEnableDepthTesting - enables per pixel depth testing, as in
+ *   glEnable(GL_DEPTH_TEST);
+ * - inEnableDepthWriting - enables writing back of depth information to the
+ *   depth buffer, as in glDepthMask(GL_TRUE);
+ * 
+ * The purpose of this function is to change OpenGL state while keeping
+ * X-Plane aware of the state changes; this keeps X-Plane from getting
+ * surprised by OGL state changes, and prevents X-Plane and plug-ins from
+ * having to set all state before all draws; XPLMSetGraphicsState internally
+ * skips calls to change state that is already properly enabled.
+ * 
+ * X-Plane does not have a 'default' OGL state for plug-ins with respect to
+ * the above state vector; plug-ins should totally set OGL state using this
+ * API before drawing.  Use XPLMSetGraphicsState instead of any of the above
+ * OpenGL calls.
+ * 
+ * WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget
+ * code) may change X-Plane's state.  Always set state before drawing after
+ * unknown code has executed.
+ * 
+ * *Deprecation Warnings*: X-Plane's lighting and fog environment is
+ *  significantly more complex than the fixed function pipeline can express;
+ *  do not assume that lighting and fog state is a good approximation for 3-d
+ *  drawing.  Prefer to use XPLMInstancing to draw objects.  All calls to
+ *  XPLMSetGraphicsState should have no fog or lighting.
+ *
+ */
+XPLM_API void       XPLMSetGraphicsState(
+                         int                  inEnableFog,
+                         int                  inNumberTexUnits,
+                         int                  inEnableLighting,
+                         int                  inEnableAlphaTesting,
+                         int                  inEnableAlphaBlending,
+                         int                  inEnableDepthTesting,
+                         int                  inEnableDepthWriting);
+
+/*
+ * XPLMBindTexture2d
+ * 
+ *  XPLMBindTexture2d changes what texture is bound to the 2d texturing
+ *  target. This routine caches the current 2d texture across all texturing
+ *  units in the sim and plug-ins, preventing extraneous binding.  For
+ *  example, consider several plug-ins running in series; if they all use the
+ *  'general interface' bitmap to do UI, calling this function will skip the
+ *  rebinding of the general interface texture on all but the first plug-in,
+ *  which can provide better frame rates on some graphics cards.
+ * 
+ * inTextureID is the ID of the texture object to bind; inTextureUnit is a
+ * zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4
+ * units.  (This number may increase in future versions of X-Plane.)
+ * 
+ * Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....);
+ *
+ */
+XPLM_API void       XPLMBindTexture2d(
+                         int                  inTextureNum,
+                         int                  inTextureUnit);
+
+/*
+ * XPLMGenerateTextureNumbers
+ * 
+ * Use this routine instead of glGenTextures to generate new texture object
+ * IDs. This routine historically ensured that plugins don't use texure IDs
+ * that X-Plane is reserving for its own use.
+ *
+ */
+XPLM_API void       XPLMGenerateTextureNumbers(
+                         int *                outTextureIDs,
+                         int                  inCount);
+
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMGetTexture
+ * 
+ * XPLMGetTexture returns the OpenGL texture ID of an X-Plane texture based on
+ * a generic identifying code.  For example, you can get the texture for
+ * X-Plane's UI bitmaps.
+ *
+ */
+XPLM_API int        XPLMGetTexture(
+                         XPLMTextureID        inTexture);
+#endif /* XPLM_DEPRECATED */
+
+/*
+ * XPLMWorldToLocal
+ * 
+ * This routine translates coordinates from latitude, longitude, and altitude
+ * to local scene coordinates. Latitude and longitude are in decimal degrees,
+ * and altitude is in meters MSL (mean sea level).  The XYZ coordinates are in
+ * meters in the local OpenGL coordinate system.
+ *
+ */
+XPLM_API void       XPLMWorldToLocal(
+                         double               inLatitude,
+                         double               inLongitude,
+                         double               inAltitude,
+                         double *             outX,
+                         double *             outY,
+                         double *             outZ);
+
+/*
+ * XPLMLocalToWorld
+ * 
+ * This routine translates a local coordinate triplet back into latitude,
+ * longitude, and altitude.  Latitude and longitude are in decimal degrees,
+ * and altitude is in meters MSL (mean sea level).  The XYZ coordinates are in
+ * meters in the local OpenGL coordinate system.
+ * 
+ * NOTE: world coordinates are less precise than local coordinates; you should
+ * try to avoid round tripping from local to world and back.
+ *
+ */
+XPLM_API void       XPLMLocalToWorld(
+                         double               inX,
+                         double               inY,
+                         double               inZ,
+                         double *             outLatitude,
+                         double *             outLongitude,
+                         double *             outAltitude);
+
+/*
+ * XPLMDrawTranslucentDarkBox
+ * 
+ * This routine draws a translucent dark box, partially obscuring parts of the
+ * screen but making text easy to read.  This is the same graphics primitive
+ * used by X-Plane to show text files.
+ *
+ */
+XPLM_API void       XPLMDrawTranslucentDarkBox(
+                         int                  inLeft,
+                         int                  inTop,
+                         int                  inRight,
+                         int                  inBottom);
+
+/***************************************************************************
+ * X-PLANE TEXT
+ ***************************************************************************/
+
+/*
+ * XPLMFontID
+ * 
+ * X-Plane features some fixed-character fonts.  Each font may have its own
+ * metrics.
+ * 
+ * WARNING: Some of these fonts are no longer supported or may have changed
+ * geometries. For maximum copmatibility, see the comments below.
+ * 
+ * Note: X-Plane 7 supports proportional-spaced fonts.  Since no measuring
+ * routine is available yet, the SDK will normally draw using a fixed-width
+ * font.  You can use a dataref to enable proportional font drawing on XP7 if
+ * you want to.
+ *
+ */
+enum {
+    /* Mono-spaced font for user interface.  Available in all versions of the SDK.*/
+    xplmFont_Basic                           = 0,
+
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_Menus                           = 1,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_Metal                           = 2,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_Led                             = 3,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_LedWide                         = 4,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_PanelHUD                        = 5,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_PanelEFIS                       = 6,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_PanelGPS                        = 7,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosGA                        = 8,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosBC                        = 9,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosHM                        = 10,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosGANarrow                  = 11,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosBCNarrow                  = 12,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_RadiosHMNarrow                  = 13,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_Timer                           = 14,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_FullRound                       = 15,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_SmallRound                      = 16,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    /* Deprecated, do not use.                                                    */
+    xplmFont_Menus_Localized                 = 17,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM200)
+    /* Proportional UI font.                                                      */
+    xplmFont_Proportional                    = 18,
+
+#endif /* XPLM200 */
+
+};
+typedef int XPLMFontID;
+
+/*
+ * XPLMDrawString
+ * 
+ * This routine draws a NULL terminated string in a given font.  Pass in the
+ * lower left pixel that the character is to be drawn onto.  Also pass the
+ * character and font ID. This function returns the x offset plus the width of
+ * all drawn characters. The color to draw in is specified as a pointer to an
+ * array of three floating point colors, representing RGB intensities from 0.0
+ * to 1.0.
+ *
+ */
+XPLM_API void       XPLMDrawString(
+                         float *              inColorRGB,
+                         int                  inXOffset,
+                         int                  inYOffset,
+                         const char *         inChar,
+                         int *                inWordWrapWidth,        /* Can be NULL */
+                         XPLMFontID           inFontID);
+
+/*
+ * XPLMDrawNumber
+ * 
+ * This routine draws a number similar to the digit editing fields in
+ * PlaneMaker and data output display in X-Plane.  Pass in a color, a
+ * position, a floating point value, and formatting info.  Specify how many
+ * integer and how many decimal digits to show and whether to show a sign, as
+ * well as a character set. This routine returns the xOffset plus width of the
+ * string drawn.
+ *
+ */
+XPLM_API void       XPLMDrawNumber(
+                         float *              inColorRGB,
+                         int                  inXOffset,
+                         int                  inYOffset,
+                         double               inValue,
+                         int                  inDigits,
+                         int                  inDecimals,
+                         int                  inShowSign,
+                         XPLMFontID           inFontID);
+
+/*
+ * XPLMGetFontDimensions
+ * 
+ * This routine returns the width and height of a character in a given font.
+ * It also tells you if the font only supports numeric digits.  Pass NULL if
+ * you don't need a given field.  Note that for a proportional font the width
+ * will be an arbitrary, hopefully average width.
+ *
+ */
+XPLM_API void       XPLMGetFontDimensions(
+                         XPLMFontID           inFontID,
+                         int *                outCharWidth,           /* Can be NULL */
+                         int *                outCharHeight,          /* Can be NULL */
+                         int *                outDigitsOnly);         /* Can be NULL */
+
+#if defined(XPLM200)
+/*
+ * XPLMMeasureString
+ * 
+ * This routine returns the width in pixels of a string using a given font. 
+ * The string is passed as a pointer plus length (and does not need to be null
+ * terminated); this is used to allow for measuring substrings. The return
+ * value is floating point; it is possible that future font drawing may allow
+ * for fractional pixels.
+ *
+ */
+XPLM_API float      XPLMMeasureString(
+                         XPLMFontID           inFontID,
+                         const char *         inChar,
+                         int                  inNumChars);
+#endif /* XPLM200 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMInstance.h b/SDK/CHeaders/XPLM/XPLMInstance.h
new file mode 100644
index 0000000..f2460fb
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMInstance.h
@@ -0,0 +1,136 @@
+#ifndef _XPLMInstance_h_
+#define _XPLMInstance_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMInstance
+ ***************************************************************************/
+/*
+ * This API provides instanced drawing of X-Plane objects (.obj files). In
+ * contrast to old drawing APIs, which required you to draw your own objects
+ * per-frame, the instancing API allows you to simply register an OBJ for
+ * drawing, then move or manipulate it later (as needed).
+ * 
+ * This provides one tremendous benefit: it keeps all dataref operations for
+ * your object in one place. Because datarefs access may be done from the main
+ * thread only, allowing dataref access anywhere is a serious performance
+ * bottleneck for the simulator - the whole simulator has to pause and wait
+ * for each dataref access. This performance penalty will only grow worse as
+ * X-Plane moves toward an ever more heavily multithreaded engine.
+ * 
+ * The instancing API allows X-Plane to isolate all dataref manipulations for
+ * all plugin object drawing to one place, potentially providing huge
+ * performance gains.
+ * 
+ * Here's how it works:
+ * 
+ * When an instance is created, it provides a list of all datarefs you want to
+ * manipulate for the OBJ in the future. This list of datarefs replaces the
+ * ad-hoc collections of dataref objects previously used by art assets. Then,
+ * per-frame, you can manipulate the instance by passing in a "block" of
+ * packed floats representing the current values of the datarefs for your
+ * instance. (Note that the ordering of this set of packed floats must exactly
+ * match the ordering of the datarefs when you created your instance.)
+ *
+ */
+
+#include "XPLMDefs.h"
+#include "XPLMScenery.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * Instance Creation and Destruction
+ ***************************************************************************/
+/*
+ * Registers and unregisters instances.
+ *
+ */
+
+
+/*
+ * XPLMInstanceRef
+ * 
+ * An opaque handle to an instance.
+ *
+ */
+typedef void * XPLMInstanceRef;
+
+/*
+ * XPLMCreateInstance
+ * 
+ * XPLMCreateInstance creates a new instance, managed by your plug-in, and
+ * returns a handle to the instance. A few important requirements:
+ * 
+ * * The object passed in must be fully loaded and returned from the XPLM
+ *   before you can create your instance; you cannot pass a null obj ref, nor
+ *   can you change the ref later.
+ * 
+ * * If you use any custom datarefs in your object, they must be registered
+ *   before the object is loaded. This is true even if their data will be
+ *   provided via the instance dataref list.
+ * 
+ * * The instance dataref array must be a valid pointer to a null-terminated
+ *   array.  That is, if you do not want any datarefs, you must pass a pointer
+ *   to a one-element array containing a null item.  You cannot pass null for
+ *   the array itself.
+ *
+ */
+XPLM_API XPLMInstanceRef XPLMCreateInstance(
+                         XPLMObjectRef        obj,
+                         const char **        datarefs);
+
+/*
+ * XPLMDestroyInstance
+ * 
+ * XPLMDestroyInstance destroys and deallocates your instance; once called,
+ * you are still responsible for releasing the OBJ ref.
+ * 
+ * Tip: you can release your OBJ ref after you call XPLMCreateInstance as long
+ * as you never use it again; the instance will maintain its own reference to
+ * the OBJ and the object OBJ be deallocated when the instance is destroyed.
+ *
+ */
+XPLM_API void       XPLMDestroyInstance(
+                         XPLMInstanceRef      instance);
+
+/***************************************************************************
+ * Instance Manipulation
+ ***************************************************************************/
+
+/*
+ * XPLMInstanceSetPosition
+ * 
+ * Updates both the position of the instance and all datarefs you registered
+ * for it.  Call this from a flight loop callback or UI callback.
+ * 
+ * __DO_NOT__ call XPLMInstanceSetPosition from a drawing callback; the whole
+ * point of instancing is that you do not need any drawing callbacks. Setting
+ * instance data from a drawing callback may have undefined consequences, and
+ * the drawing callback hurts FPS unnecessarily.  
+ * 
+ * The memory pointed to by the data pointer must be large enough to hold one
+ * float for every dataref you have registered, and must contain valid
+ * floating point data.
+ * 
+ * BUG: before X-Plane 11.50, if you have no dataref registered, you must
+ * still pass a valid pointer for data and not null.
+ *
+ */
+XPLM_API void       XPLMInstanceSetPosition(
+                         XPLMInstanceRef      instance,
+                         const XPLMDrawInfo_t * new_position,
+                         const float *        data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMMap.h b/SDK/CHeaders/XPLM/XPLMMap.h
new file mode 100644
index 0000000..de77144
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMMap.h
@@ -0,0 +1,628 @@
+#ifndef _XPLMMap_h_
+#define _XPLMMap_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMMap
+ ***************************************************************************/
+/*
+ * This API allows you to create new layers within X-Plane maps. Your layers
+ * can draw arbitrary OpenGL, but they conveniently also have access to
+ * X-Plane's built-in icon and label drawing functions.
+ * 
+ * As of X-Plane 11, map drawing happens in three stages:
+ * 
+ * 1. backgrounds and "fill",
+ * 2. icons, and
+ * 3. labels.
+ * 
+ * Thus, all background drawing gets layered beneath all icons, which likewise
+ * get layered beneath all labels. Within each stage, the map obeys a
+ * consistent layer ordering, such that "fill" layers (layers that cover a
+ * large amount of map area, like the terrain and clouds) appear beneath
+ * "markings" layers (like airport icons). This ensures that layers with fine
+ * details don't get obscured by layers with larger details.
+ * 
+ * The XPLM map API reflects both aspects of this draw layering: you can
+ * register a layer as providing either markings or fill, and X-Plane will
+ * draw your fill layers beneath your markings layers (regardless of
+ * registration order). Likewise, you are guaranteed that your layer's icons
+ * (added from within an icon callback) will go above your layer's OpenGL
+ * drawing, and your labels will go above your icons.
+ * 
+ * The XPLM guarantees that all plugin-created fill layers go on top of all
+ * native X-Plane fill layers, and all plugin-created markings layers go on
+ * top of all X-Plane markings layers (with the exception of the aircraft
+ * icons). It also guarantees that the draw order of your own plugin's layers
+ * will be consistent. But, for layers created by different plugins, the only
+ * guarantee is that we will draw all of one plugin's layers of each type
+ * (fill, then markings), then all of the others'; we don't guarantee which
+ * plugin's fill and markings layers go on top of the other's.
+ * 
+ * As of X-Plane 11, maps use true cartographic projections for their drawing,
+ * and different maps may use different projections. For that reason, all
+ * drawing calls include an opaque handle for the projection you should use to
+ * do the drawing. Any time you would draw at a particular latitude/longitude,
+ * you'll need to ask the projection to translate that position into "map
+ * coordinates." (Note that the projection is guaranteed not to change between
+ * calls to your prepare-cache hook, so if you cache your map coordinates
+ * ahead of time, there's no need to re-project them when you actually draw.)
+ * 
+ * In addition to mapping normal latitude/longitude locations into map
+ * coordinates, the projection APIs also let you know the current heading for
+ * north. (Since X-Plane 11 maps can rotate to match the heading of the user's
+ * aircraft, it's not safe to assume that north is at zero degrees rotation.)
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(XPLM300)
+/***************************************************************************
+ * DRAWING CALLBACKS
+ ***************************************************************************/
+/*
+ * When you create a new map layer (using XPLMCreateMapLayer), you can provide
+ * any or all of these callbacks. They allow you to insert your own OpenGL
+ * drawing, text labels, and icons into the X-Plane map at the appropriate
+ * places, allowing your layer to behave as similarly to X-Plane's built-in
+ * layers as possible.
+ *
+ */
+
+
+/*
+ * XPLMMapLayerID
+ * 
+ * This is an opaque handle for a plugin-created map layer. Pass it to the map
+ * drawing APIs from an appropriate callback to draw in the layer you created.
+ *
+ */
+typedef void * XPLMMapLayerID;
+
+/*
+ * XPLMMapProjectionID
+ * 
+ * This is an opaque handle for a map projection. Pass it to the projection
+ * APIs to translate between map coordinates and latitude/longitudes.
+ *
+ */
+typedef void * XPLMMapProjectionID;
+
+/*
+ * XPLMMapStyle
+ * 
+ * Indicates the visual style being drawn by the map. In X-Plane, the user can
+ * choose between a number of map types, and different map types may have use
+ * a different visual representation for the same elements (for instance, the
+ * visual style of the terrain layer changes drastically between the VFR and
+ * IFR layers), or certain layers may be disabled entirely in some map types
+ * (e.g., localizers are only visible in the IFR low-enroute style).
+ *
+ */
+enum {
+    xplm_MapStyle_VFR_Sectional              = 0,
+
+    xplm_MapStyle_IFR_LowEnroute             = 1,
+
+    xplm_MapStyle_IFR_HighEnroute            = 2,
+
+
+};
+typedef int XPLMMapStyle;
+
+/*
+ * XPLMMapDrawingCallback_f
+ * 
+ * This is the OpenGL map drawing callback for plugin-created map layers. You
+ * can perform arbitrary OpenGL drawing from this callback, with one
+ * exception: changes to the Z-buffer are not permitted, and will result in
+ * map drawing errors.
+ * 
+ * All drawing done from within this callback appears beneath all built-in
+ * X-Plane icons and labels, but above the built-in "fill" layers (layers
+ * providing major details, like terrain and water). Note, however, that the
+ * relative ordering between the drawing callbacks of different plugins is not
+ * guaranteed.
+ *
+ */
+typedef void (* XPLMMapDrawingCallback_f)(
+                         XPLMMapLayerID       inLayer,
+                         const float *        inMapBoundsLeftTopRightBottom,
+                         float                zoomRatio,
+                         float                mapUnitsPerUserInterfaceUnit,
+                         XPLMMapStyle         mapStyle,
+                         XPLMMapProjectionID  projection,
+                         void *               inRefcon);
+
+/*
+ * XPLMMapIconDrawingCallback_f
+ * 
+ * This is the icon drawing callback that enables plugin-created map layers to
+ * draw icons using X-Plane's built-in icon drawing functionality. You can
+ * request an arbitrary number of PNG icons to be drawn via
+ * XPLMDrawMapIconFromSheet() from within this callback, but you may not
+ * perform any OpenGL drawing here.
+ * 
+ * Icons enqueued by this function will appear above all OpenGL drawing
+ * (performed by your optional XPLMMapDrawingCallback_f), and above all
+ * built-in X-Plane map icons of the same layer type ("fill" or "markings," as
+ * determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
+ * however, that the relative ordering between the drawing callbacks of
+ * different plugins is not guaranteed.
+ *
+ */
+typedef void (* XPLMMapIconDrawingCallback_f)(
+                         XPLMMapLayerID       inLayer,
+                         const float *        inMapBoundsLeftTopRightBottom,
+                         float                zoomRatio,
+                         float                mapUnitsPerUserInterfaceUnit,
+                         XPLMMapStyle         mapStyle,
+                         XPLMMapProjectionID  projection,
+                         void *               inRefcon);
+
+/*
+ * XPLMMapLabelDrawingCallback_f
+ * 
+ * This is the label drawing callback that enables plugin-created map layers
+ * to draw text labels using X-Plane's built-in labeling functionality. You
+ * can request an arbitrary number of text labels to be drawn via
+ * XPLMDrawMapLabel() from within this callback, but you may not perform any
+ * OpenGL drawing here.
+ * 
+ * Labels enqueued by this function will appear above all OpenGL drawing
+ * (performed by your optional XPLMMapDrawingCallback_f), and above all
+ * built-in map icons and labels of the same layer type ("fill" or "markings,"
+ * as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
+ * however, that the relative ordering between the drawing callbacks of
+ * different plugins is not guaranteed.
+ *
+ */
+typedef void (* XPLMMapLabelDrawingCallback_f)(
+                         XPLMMapLayerID       inLayer,
+                         const float *        inMapBoundsLeftTopRightBottom,
+                         float                zoomRatio,
+                         float                mapUnitsPerUserInterfaceUnit,
+                         XPLMMapStyle         mapStyle,
+                         XPLMMapProjectionID  projection,
+                         void *               inRefcon);
+
+#endif /* XPLM300 */
+#if defined(XPLM300)
+/***************************************************************************
+ * LAYER MANAGEMENT CALLBACKS
+ ***************************************************************************/
+/*
+ * These are various "bookkeeping" callbacks that your map layer can receive
+ * (if you provide the callback in your XPLMCreateMapLayer_t). They allow you
+ * to manage the lifecycle of your layer, as well as cache any
+ * computationally-intensive preparation you might need for drawing.
+ *
+ */
+
+
+/*
+ * XPLMMapPrepareCacheCallback_f
+ * 
+ * A callback used to allow you to cache whatever information your layer needs
+ * to draw in the current map area.
+ * 
+ * This is called each time the map's total bounds change. This is typically
+ * triggered by new DSFs being loaded, such that X-Plane discards old,
+ * now-distant DSFs and pulls in new ones. At that point, the available bounds
+ * of the map also change to match the new DSF area.
+ * 
+ * By caching just the information you need to draw in this area, your future
+ * draw calls can be made faster, since you'll be able to simply "splat" your
+ * precomputed information each frame.
+ * 
+ * We guarantee that the map projection will not change between successive
+ * prepare cache calls, nor will any draw call give you bounds outside these
+ * total map bounds. So, if you cache the projected map coordinates of all the
+ * items you might want to draw in the total map area, you can be guaranteed
+ * that no draw call will be asked to do any new work.
+ *
+ */
+typedef void (* XPLMMapPrepareCacheCallback_f)(
+                         XPLMMapLayerID       inLayer,
+                         const float *        inTotalMapBoundsLeftTopRightBottom,
+                         XPLMMapProjectionID  projection,
+                         void *               inRefcon);
+
+/*
+ * XPLMMapWillBeDeletedCallback_f
+ * 
+ * Called just before your map layer gets deleted. Because SDK-created map
+ * layers have the same lifetime as the X-Plane map that contains them, if the
+ * map gets unloaded from memory, your layer will too.
+ *
+ */
+typedef void (* XPLMMapWillBeDeletedCallback_f)(
+                         XPLMMapLayerID       inLayer,
+                         void *               inRefcon);
+
+#endif /* XPLM300 */
+#if defined(XPLM300)
+/***************************************************************************
+ * MAP LAYER CREATION AND DESTRUCTION
+ ***************************************************************************/
+/*
+ * Enables the creation of new map layers. Layers are created for a particular
+ * instance of the X-Plane map. For instance, if you want your layer to appear
+ * in both the normal map interface and the Instructor Operator Station (IOS),
+ * you would need two separate calls to XPLMCreateMapLayer(), with two
+ * different values for your XPLMCreateMapLayer_t::layer_name.
+ * 
+ * Your layer's lifetime will be determined by the lifetime of the map it is
+ * created in. If the map is destroyed (on the X-Plane side), your layer will
+ * be too, and you'll receive a callback to your
+ * XPLMMapWillBeDeletedCallback_f.
+ *
+ */
+
+
+/*
+ * XPLMMapLayerType
+ * 
+ * Indicates the type of map layer you are creating. Fill layers will always
+ * be drawn beneath markings layers.
+ *
+ */
+enum {
+    /* A layer that draws "fill" graphics, like weather patterns, terrain, etc.   *
+     * Fill layers frequently cover a large portion of the visible map area.      */
+    xplm_MapLayer_Fill                       = 0,
+
+    /* A layer that provides markings for particular map features, like NAVAIDs,  *
+     * airports, etc. Even dense markings layers cover a small portion of the     *
+     * total map area.                                                            */
+    xplm_MapLayer_Markings                   = 1,
+
+
+};
+typedef int XPLMMapLayerType;
+
+/* Globally unique identifier for X-Plane's Map window, used as the           *
+ * mapToCreateLayerIn parameter in XPLMCreateMapLayer_t                       */
+#define XPLM_MAP_USER_INTERFACE "XPLM_MAP_USER_INTERFACE"
+
+/* Globally unique identifier for X-Plane's Instructor Operator Station       *
+ * window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t   */
+#define XPLM_MAP_IOS         "XPLM_MAP_IOS"
+
+/*
+ * XPLMCreateMapLayer_t
+ * 
+ * This structure defines all of the parameters used to create a map layer
+ * using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs
+ * to include more features.  Always set the structSize member to the size of
+ * your struct in bytes!
+ * 
+ * Each layer must be associated with exactly one map instance in X-Plane.
+ * That map, and that map alone, will call your callbacks. Likewise, when that
+ * map is deleted, your layer will be as well.
+ *
+ */
+typedef struct {
+    /* Used to inform XPLMCreateMapLayer() of the SDK version you compiled        *
+     * against; should always be set to sizeof(XPLMCreateMapLayer_t)              */
+     int                       structSize;
+    /* Globally unique string identifying the map you want this layer to appear   *
+     * in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or    *
+     * XPLM_MAP_IOS                                                               */
+     const char *              mapToCreateLayerIn;
+    /* The type of layer you are creating, used to determine draw order (all      *
+     * plugin-created markings layers are drawn above all plugin-created fill     *
+     * layers)                                                                    */
+     XPLMMapLayerType          layerType;
+    /* Optional callback to inform you this layer is being deleted (due to its    *
+     * owning map being destroyed)                                                */
+     XPLMMapWillBeDeletedCallback_f willBeDeletedCallback;
+    /* Optional callback you want to use to prepare your draw cache when the map  *
+     * bounds change (set to NULL if you don't want this callback)                */
+     XPLMMapPrepareCacheCallback_f prepCacheCallback;
+    /* Optional callback you want to use for arbitrary OpenGL drawing, which goes *
+     * beneath all icons in the map's layering system (set to NULL if you don't   *
+     * want this callback)                                                        */
+     XPLMMapDrawingCallback_f  drawCallback;
+    /* Optional callback you want to use for drawing icons, which go above all    *
+     * built-in X-Plane icons (except the aircraft) in the map's layering system  *
+     * (set to NULL if you don't want this callback)                              */
+     XPLMMapIconDrawingCallback_f iconCallback;
+    /* Optional callback you want to use for drawing map labels, which go above   *
+     * all built-in X-Plane icons and labels (except those of aircraft) in the    *
+     * map's layering system (set to NULL if you don't want this callback)        */
+     XPLMMapLabelDrawingCallback_f labelCallback;
+    /* True if you want a checkbox to be created in the map UI to toggle this     *
+     * layer on and off; false if the layer should simply always be enabled       */
+     int                       showUiToggle;
+    /* Short label to use for this layer in the user interface                    */
+     const char *              layerName;
+    /* A reference to arbitrary data that will be passed to your callbacks        */
+     void *                    refcon;
+} XPLMCreateMapLayer_t;
+
+/*
+ * XPLMCreateMapLayer
+ * 
+ * This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t
+ * structure with all of the fields defined.  You must set the structSize of
+ * the structure to the size of the actual structure you used.
+ * 
+ * Returns NULL if the layer creation failed. This happens most frequently
+ * because the map you specified in your
+ * XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if
+ * XPLMMapExists() returns 0 for the specified map). You can use
+ * XPLMRegisterMapCreationHook() to get a notification each time a new map is
+ * opened in X-Plane, at which time you can create layers in it.
+ *
+ */
+XPLM_API XPLMMapLayerID XPLMCreateMapLayer(
+                         XPLMCreateMapLayer_t * inParams);
+
+/*
+ * XPLMDestroyMapLayer
+ * 
+ * Destroys a map layer you created (calling your
+ * XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion
+ * took place.
+ *
+ */
+XPLM_API int        XPLMDestroyMapLayer(
+                         XPLMMapLayerID       inLayer);
+
+/*
+ * XPLMMapCreatedCallback_f
+ * 
+ * A callback to notify your plugin that a new map has been created in
+ * X-Plane. This is the best time to add a custom map layer using
+ * XPLMCreateMapLayer().
+ * 
+ * No OpenGL drawing is permitted within this callback.
+ *
+ */
+typedef void (* XPLMMapCreatedCallback_f)(
+                         const char *         mapIdentifier,
+                         void *               refcon);
+
+/*
+ * XPLMRegisterMapCreationHook
+ * 
+ * Registers your callback to receive a notification each time a new map is
+ * constructed in X-Plane. This callback is the best time to add your custom
+ * map layer using XPLMCreateMapLayer().
+ * 
+ * Note that you will not be notified about any maps that already exist---you
+ * can use XPLMMapExists() to check for maps that were created previously.
+ *
+ */
+XPLM_API void       XPLMRegisterMapCreationHook(
+                         XPLMMapCreatedCallback_f callback,
+                         void *               refcon);
+
+/*
+ * XPLMMapExists
+ * 
+ * Returns 1 if the map with the specified identifier already exists in
+ * X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying
+ * that your layer should be added to that map.
+ *
+ */
+XPLM_API int        XPLMMapExists(
+                         const char *         mapIdentifier);
+
+#endif /* XPLM300 */
+#if defined(XPLM300)
+/***************************************************************************
+ * MAP DRAWING
+ ***************************************************************************/
+/*
+ * These APIs are only valid from within a map drawing callback (one of
+ * XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing
+ * callbacks are registered when you create a new map layer as part of your
+ * XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map
+ * drawing functionality for icons and labels, so that you get a consistent
+ * style with the rest of the X-Plane map.
+ * 
+ * Note that the X-Plane 11 map introduces a strict ordering: layers of type
+ * xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers.
+ * Likewise, all OpenGL drawing (performed in your layer's
+ * XPLMMapDrawingCallback_f) will appear beneath any icons and labels you
+ * draw.
+ *
+ */
+
+
+/*
+ * XPLMMapOrientation
+ * 
+ * Indicates whether a map element should be match its rotation to the map
+ * itself, or to the user interface. For instance, the map itself may be
+ * rotated such that "up" matches the user's aircraft, but you may want to
+ * draw a text label such that it is always rotated zero degrees relative to
+ * the user's perspective. In that case, you would have it draw with UI
+ * orientation.
+ *
+ */
+enum {
+    /* Orient such that a 0 degree rotation matches the map's north               */
+    xplm_MapOrientation_Map                  = 0,
+
+    /* Orient such that a 0 degree rotation is "up" relative to the user interface*/
+    xplm_MapOrientation_UI                   = 1,
+
+
+};
+typedef int XPLMMapOrientation;
+
+/*
+ * XPLMDrawMapIconFromSheet
+ * 
+ * Enables plugin-created map layers to draw PNG icons using X-Plane's
+ * built-in icon drawing functionality. Only valid from within an
+ * XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons
+ * to be drawn from within your callback).
+ * 
+ * X-Plane will automatically manage the memory for your texture so that it
+ * only has to be loaded from disk once as long as you continue drawing it
+ * per-frame. (When you stop drawing it, the memory may purged in a "garbage
+ * collection" pass, require a load from disk in the future.)
+ * 
+ * Instead of having X-Plane draw a full PNG, this method allows you to use UV
+ * coordinates to request a portion of the image to be drawn. This allows you
+ * to use a single texture load (of an icon sheet, for example) to draw many
+ * icons. Doing so is much more efficient than drawing a dozen different small
+ * PNGs.
+ * 
+ * The UV coordinates used here treat the texture you load as being comprised
+ * of a number of identically sized "cells". You specify the width and height
+ * in cells (ds and dt, respectively), as well as the coordinates within the
+ * cell grid for the sub-image you'd like to draw.
+ * 
+ * Note that you can use different ds and dt values in subsequent calls with
+ * the same texture sheet. This enables you to use icons of different sizes in
+ * the same sheet if you arrange them properly in the PNG.
+ * 
+ * This function is only valid from within an XPLMIconDrawingCallback_t (but
+ * you can request an arbitrary number of icons to be drawn from within your
+ * callback).
+ *
+ */
+XPLM_API void       XPLMDrawMapIconFromSheet(
+                         XPLMMapLayerID       layer,
+                         const char *         inPngPath,
+                         int                  s,
+                         int                  t,
+                         int                  ds,
+                         int                  dt,
+                         float                mapX,
+                         float                mapY,
+                         XPLMMapOrientation   orientation,
+                         float                rotationDegrees,
+                         float                mapWidth);
+
+/*
+ * XPLMDrawMapLabel
+ * 
+ * Enables plugin-created map layers to draw text labels using X-Plane's
+ * built-in labeling functionality. Only valid from within an
+ * XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of
+ * text labels to be drawn from within your callback).
+ *
+ */
+XPLM_API void       XPLMDrawMapLabel(
+                         XPLMMapLayerID       layer,
+                         const char *         inText,
+                         float                mapX,
+                         float                mapY,
+                         XPLMMapOrientation   orientation,
+                         float                rotationDegrees);
+
+#endif /* XPLM300 */
+#if defined(XPLM300)
+/***************************************************************************
+ * MAP PROJECTIONS
+ ***************************************************************************/
+/*
+ * As of X-Plane 11, the map draws using true cartographic projections, and
+ * different maps may use different projections. Thus, to draw at a particular
+ * latitude and longitude, you must first transform your real-world
+ * coordinates into map coordinates.
+ * 
+ * The map projection is also responsible for giving you the current scale of
+ * the map. That is, the projection can tell you how many map units correspond
+ * to 1 meter at a given point.
+ * 
+ * Finally, the map projection can give you the current rotation of the map.
+ * Since X-Plane 11 maps can rotate to match the heading of the aircraft, the
+ * map's rotation can potentially change every frame.
+ *
+ */
+
+
+/*
+ * XPLMMapProject
+ * 
+ * Projects a latitude/longitude into map coordinates. This is the inverse of
+ * XPLMMapUnproject().
+ * 
+ * Only valid from within a map layer callback (one of
+ * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+ * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+ *
+ */
+XPLM_API void       XPLMMapProject(
+                         XPLMMapProjectionID  projection,
+                         double               latitude,
+                         double               longitude,
+                         float *              outX,
+                         float *              outY);
+
+/*
+ * XPLMMapUnproject
+ * 
+ * Transforms map coordinates back into a latitude and longitude. This is the
+ * inverse of XPLMMapProject().
+ * 
+ * Only valid from within a map layer callback (one of
+ * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+ * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+ *
+ */
+XPLM_API void       XPLMMapUnproject(
+                         XPLMMapProjectionID  projection,
+                         float                mapX,
+                         float                mapY,
+                         double *             outLatitude,
+                         double *             outLongitude);
+
+/*
+ * XPLMMapScaleMeter
+ * 
+ * Returns the number of map units that correspond to a distance of one meter
+ * at a given set of map coordinates.
+ * 
+ * Only valid from within a map layer callback (one of
+ * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+ * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+ *
+ */
+XPLM_API float      XPLMMapScaleMeter(
+                         XPLMMapProjectionID  projection,
+                         float                mapX,
+                         float                mapY);
+
+/*
+ * XPLMMapGetNorthHeading
+ * 
+ * Returns the heading (in degrees clockwise) from the positive Y axis in the
+ * cartesian mapping coordinate system to true north at the point passed in. 
+ * You can use it as a clockwise rotational offset to align icons and other
+ * 2-d drawing with true north on the map, compensating for rotations in the
+ * map due to projection.
+ * 
+ * Only valid from within a map layer callback (one of
+ * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+ * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+ *
+ */
+XPLM_API float      XPLMMapGetNorthHeading(
+                         XPLMMapProjectionID  projection,
+                         float                mapX,
+                         float                mapY);
+
+#endif /* XPLM300 */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMMenus.h b/SDK/CHeaders/XPLM/XPLMMenus.h
new file mode 100644
index 0000000..2c8fcd0
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMMenus.h
@@ -0,0 +1,290 @@
+#ifndef _XPLMMenus_h_
+#define _XPLMMenus_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMMenus
+ ***************************************************************************/
+/*
+ * Plug-ins can create menus in the menu bar of X-Plane.  This is done by
+ * creating a menu and then creating items.  Menus are referred to by an
+ * opaque ID.  Items are referred to by (zero-based) index number.
+ * 
+ * Menus are "sandboxed" between plugins - no plugin can access the menus of
+ * any other plugin. Furthermore, all menu indices are relative to your
+ * plugin's menus only; if your plugin creates two sub-menus in the Plugins
+ * menu at different times, it doesn't matter how many other plugins also
+ * create sub-menus of Plugins in the intervening time: your sub-menus will be
+ * given menu indices 0 and 1. (The SDK does some work in the back-end to
+ * filter out menus that are irrelevant to your plugin in order to deliver
+ * this consistency for each plugin.)
+ * 
+ * When you create a menu item, you specify how we should handle clicks on
+ * that menu item. You can either have the XPLM trigger a callback (the
+ * XPLMMenuHandler_f associated with the menu that contains the item), or you
+ * can simply have a command be triggered (with no associated call to your
+ * menu handler). The advantage of the latter method is that X-Plane will
+ * display any keyboard shortcuts associated with the command. (In contrast,
+ * there are no keyboard shortcuts associated with menu handler callbacks with
+ * specific parameters.)
+ * 
+ * Menu text in X-Plane is UTF8; X-Plane's character set covers latin, greek
+ * and cyrillic characters, Katakana, as well as some Japanese symbols. Some
+ * APIs have a inDeprecatedAndIgnored parameter that used to select a
+ * character set; since X-Plane 9 all localization is done via UTF-8 only.
+ *
+ */
+
+#include "XPLMDefs.h"
+#include "XPLMUtilities.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * XPLM MENUS
+ ***************************************************************************/
+
+/*
+ * XPLMMenuCheck
+ * 
+ * These enumerations define the various 'check' states for an X-Plane menu. 
+ * 'Checking' in X-Plane actually appears as a light which may or may not be
+ * lit.  So there are three possible states.
+ *
+ */
+enum {
+    /* There is no symbol to the left of the menu item.                           */
+    xplm_Menu_NoCheck                        = 0,
+
+    /* The menu has a mark next to it that is unmarked (not lit).                 */
+    xplm_Menu_Unchecked                      = 1,
+
+    /* The menu has a mark next to it that is checked (lit).                      */
+    xplm_Menu_Checked                        = 2,
+
+
+};
+typedef int XPLMMenuCheck;
+
+/*
+ * XPLMMenuID
+ * 
+ * This is a unique ID for each menu you create.
+ *
+ */
+typedef void * XPLMMenuID;
+
+/*
+ * XPLMMenuHandler_f
+ * 
+ * A menu handler function takes two reference pointers, one for the menu
+ * (specified when the menu was created) and one for the item (specified when
+ * the item was created).
+ *
+ */
+typedef void (* XPLMMenuHandler_f)(
+                         void *               inMenuRef,
+                         void *               inItemRef);
+
+/*
+ * XPLMFindPluginsMenu
+ * 
+ * This function returns the ID of the plug-ins menu, which is created for you
+ * at startup.
+ *
+ */
+XPLM_API XPLMMenuID XPLMFindPluginsMenu(void);
+
+#if defined(XPLM300)
+/*
+ * XPLMFindAircraftMenu
+ * 
+ * This function returns the ID of the menu for the currently-loaded aircraft,
+ * used for showing aircraft-specific commands.
+ * 
+ * The aircraft menu is created by X-Plane at startup, but it remains hidden
+ * until it is populated via XPLMAppendMenuItem() or
+ * XPLMAppendMenuItemWithCommand().
+ * 
+ * Only plugins loaded with the user's current aircraft are allowed to access
+ * the aircraft menu. For all other plugins, this will return NULL, and any
+ * attempts to add menu items to it will fail.
+ *
+ */
+XPLM_API XPLMMenuID XPLMFindAircraftMenu(void);
+#endif /* XPLM300 */
+
+/*
+ * XPLMCreateMenu
+ * 
+ * This function creates a new menu and returns its ID.  It returns NULL if
+ * the menu cannot be created.  Pass in a parent menu ID and an item index to
+ * create a submenu, or NULL for the parent menu to put the menu in the menu
+ * bar.  The menu's name is only used if the menu is in the menubar.  You also
+ * pass a handler function and a menu reference value. Pass NULL for the
+ * handler if you do not need callbacks from the menu (for example, if it only
+ * contains submenus).
+ * 
+ * Important: you must pass a valid, non-empty menu title even if the menu is
+ * a submenu where the title is not visible.
+ *
+ */
+XPLM_API XPLMMenuID XPLMCreateMenu(
+                         const char *         inName,
+                         XPLMMenuID           inParentMenu,
+                         int                  inParentItem,
+                         XPLMMenuHandler_f    inHandler,
+                         void *               inMenuRef);
+
+/*
+ * XPLMDestroyMenu
+ * 
+ * This function destroys a menu that you have created.  Use this to remove a
+ * submenu if necessary.  (Normally this function will not be necessary.)
+ *
+ */
+XPLM_API void       XPLMDestroyMenu(
+                         XPLMMenuID           inMenuID);
+
+/*
+ * XPLMClearAllMenuItems
+ * 
+ * This function removes all menu items from a menu, allowing you to rebuild
+ * it.  Use this function if you need to change the number of items on a menu.
+ *
+ */
+XPLM_API void       XPLMClearAllMenuItems(
+                         XPLMMenuID           inMenuID);
+
+/*
+ * XPLMAppendMenuItem
+ * 
+ * This routine appends a new menu item to the bottom of a menu and returns
+ * its index. Pass in the menu to add the item to, the items name, and a void
+ * * ref for this item.
+ * 
+ * Returns a negative index if the append failed (due to an invalid parent
+ * menu argument).
+ * 
+ * Note that all menu indices returned are relative to your plugin's menus
+ * only; if your plugin creates two sub-menus in the Plugins menu at different
+ * times, it doesn't matter how many other plugins also create sub-menus of
+ * Plugins in the intervening time: your sub-menus will be given menu indices
+ * 0 and 1. (The SDK does some work in the back-end to filter out menus that
+ * are irrelevant to your plugin in order to deliver this consistency for each
+ * plugin.)
+ *
+ */
+XPLM_API int        XPLMAppendMenuItem(
+                         XPLMMenuID           inMenu,
+                         const char *         inItemName,
+                         void *               inItemRef,
+                         int                  inDeprecatedAndIgnored);
+
+#if defined(XPLM300)
+/*
+ * XPLMAppendMenuItemWithCommand
+ * 
+ * Like XPLMAppendMenuItem(), but instead of the new menu item triggering the
+ * XPLMMenuHandler_f of the containiner menu, it will simply execute the
+ * command you pass in. Using a command for your menu item allows the user to
+ * bind a keyboard shortcut to the command and see that shortcut represented
+ * in the menu.
+ * 
+ * Returns a negative index if the append failed (due to an invalid parent
+ * menu argument).
+ * 
+ * Like XPLMAppendMenuItem(), all menu indices are relative to your plugin's
+ * menus only.
+ *
+ */
+XPLM_API int        XPLMAppendMenuItemWithCommand(
+                         XPLMMenuID           inMenu,
+                         const char *         inItemName,
+                         XPLMCommandRef       inCommandToExecute);
+#endif /* XPLM300 */
+
+/*
+ * XPLMAppendMenuSeparator
+ * 
+ * This routine adds a separator to the end of a menu.
+ * 
+ * Returns a negative index if the append failed (due to an invalid parent
+ * menu argument).
+ *
+ */
+XPLM_API void       XPLMAppendMenuSeparator(
+                         XPLMMenuID           inMenu);
+
+/*
+ * XPLMSetMenuItemName
+ * 
+ * This routine changes the name of an existing menu item.  Pass in the menu
+ * ID and the index of the menu item.
+ *
+ */
+XPLM_API void       XPLMSetMenuItemName(
+                         XPLMMenuID           inMenu,
+                         int                  inIndex,
+                         const char *         inItemName,
+                         int                  inDeprecatedAndIgnored);
+
+/*
+ * XPLMCheckMenuItem
+ * 
+ * Set whether a menu item is checked.  Pass in the menu ID and item index.
+ *
+ */
+XPLM_API void       XPLMCheckMenuItem(
+                         XPLMMenuID           inMenu,
+                         int                  index,
+                         XPLMMenuCheck        inCheck);
+
+/*
+ * XPLMCheckMenuItemState
+ * 
+ * This routine returns whether a menu item is checked or not. A menu item's
+ * check mark may be on or off, or a menu may not have an icon at all.
+ *
+ */
+XPLM_API void       XPLMCheckMenuItemState(
+                         XPLMMenuID           inMenu,
+                         int                  index,
+                         XPLMMenuCheck *      outCheck);
+
+/*
+ * XPLMEnableMenuItem
+ * 
+ * Sets whether this menu item is enabled.  Items start out enabled.
+ *
+ */
+XPLM_API void       XPLMEnableMenuItem(
+                         XPLMMenuID           inMenu,
+                         int                  index,
+                         int                  enabled);
+
+#if defined(XPLM210)
+/*
+ * XPLMRemoveMenuItem
+ * 
+ * Removes one item from a menu.  Note that all menu items below are moved up
+ * one; your plugin must track the change in index numbers.
+ *
+ */
+XPLM_API void       XPLMRemoveMenuItem(
+                         XPLMMenuID           inMenu,
+                         int                  inIndex);
+#endif /* XPLM210 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMNavigation.h b/SDK/CHeaders/XPLM/XPLMNavigation.h
new file mode 100644
index 0000000..c26ed3b
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMNavigation.h
@@ -0,0 +1,604 @@
+#ifndef _XPLMNavigation_h_
+#define _XPLMNavigation_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMNavigation
+ ***************************************************************************/
+/*
+ * The XPLM Navigation APIs give you some access to the navigation databases
+ * inside X-Plane.  X-Plane stores all navigation information in RAM, so by
+ * using these APIs you can gain access to most information without having to
+ * go to disk or parse the files yourself.
+ * 
+ * You can also use this API to program the FMS.  You must use the navigation
+ * APIs to find the nav-aids you want to program into the FMS, since the FMS
+ * is powered internally by X-Plane's navigation database.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * NAVIGATION DATABASE ACCESS
+ ***************************************************************************/
+
+/*
+ * XPLMNavType
+ * 
+ * These enumerations define the different types of navaids.  They are each
+ * defined with a separate bit so that they may be bit-wise added together to
+ * form sets of nav-aid types.
+ * 
+ * NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the
+ * FMS. It will not exist in the database, and cannot be programmed into the
+ * FMS. Querying the FMS for navaids will return it.  Use
+ * XPLMSetFMSEntryLatLon to set a lat/lon waypoint.
+ *
+ */
+enum {
+    xplm_Nav_Unknown                         = 0,
+
+    xplm_Nav_Airport                         = 1,
+
+    xplm_Nav_NDB                             = 2,
+
+    xplm_Nav_VOR                             = 4,
+
+    xplm_Nav_ILS                             = 8,
+
+    xplm_Nav_Localizer                       = 16,
+
+    xplm_Nav_GlideSlope                      = 32,
+
+    xplm_Nav_OuterMarker                     = 64,
+
+    xplm_Nav_MiddleMarker                    = 128,
+
+    xplm_Nav_InnerMarker                     = 256,
+
+    xplm_Nav_Fix                             = 512,
+
+    xplm_Nav_DME                             = 1024,
+
+    xplm_Nav_LatLon                          = 2048,
+
+    xplm_Nav_TACAN                           = 4096,
+
+
+};
+typedef int XPLMNavType;
+
+/*
+ * XPLMNavRef
+ * 
+ * XPLMNavRef is an iterator into the navigation database.  The navigation
+ * database is essentially an array, but it is not necessarily densely
+ * populated. The only assumption you can safely make is that like-typed
+ * nav-aids are grouped together.
+ * 
+ * Use XPLMNavRef to refer to a nav-aid.
+ * 
+ * XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when
+ * the iterator must be invalid.
+ *
+ */
+typedef int XPLMNavRef;
+
+#define XPLM_NAV_NOT_FOUND   -1
+
+/*
+ * XPLMGetFirstNavAid
+ * 
+ * This returns the very first navaid in the database.  Use this to traverse
+ * the entire database.  Returns XPLM_NAV_NOT_FOUND if the nav database is
+ * empty.
+ *
+ */
+XPLM_API XPLMNavRef XPLMGetFirstNavAid(void);
+
+/*
+ * XPLMGetNextNavAid
+ * 
+ * Given a valid navaid ref, this routine returns the next navaid.  It returns
+ * XPLM_NAV_NOT_FOUND if the navaid passed in was invalid or if the navaid
+ * passed in was the last one in the database.  Use this routine to iterate
+ * across all like-typed navaids or the entire database.
+ *
+ */
+XPLM_API XPLMNavRef XPLMGetNextNavAid(
+                         XPLMNavRef           inNavAidRef);
+
+/*
+ * XPLMFindFirstNavAidOfType
+ * 
+ * This routine returns the ref of the first navaid of the given type in the
+ * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the
+ * database.  You must pass exactly one navaid type to this routine.
+ *
+ */
+XPLM_API XPLMNavRef XPLMFindFirstNavAidOfType(
+                         XPLMNavType          inType);
+
+/*
+ * XPLMFindLastNavAidOfType
+ * 
+ * This routine returns the ref of the last navaid of the given type in the
+ * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the
+ * database.  You must pass exactly one navaid type to this routine.
+ *
+ */
+XPLM_API XPLMNavRef XPLMFindLastNavAidOfType(
+                         XPLMNavType          inType);
+
+/*
+ * XPLMFindNavAid
+ * 
+ * This routine provides a number of searching capabilities for the nav
+ * database. XPLMFindNavAid will search through every navaid whose type is
+ * within inType (multiple types may be added together) and return any navaids
+ * found based on the following rules:
+ * 
+ * * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will
+ *   be returned, otherwise the last navaid found will be returned.
+ * 
+ * * If inFrequency is not NULL, then any navaids considered must match this
+ *   frequency.  Note that this will screen out radio beacons that do not have
+ *   frequency data published (like inner markers) but not fixes and airports.
+ * 
+ * * If inNameFragment is not NULL, only navaids that contain the fragment in
+ *   their name will be returned.
+ * 
+ * * If inIDFragment is not NULL, only navaids that contain the fragment in
+ *   their IDs will be returned.
+ * 
+ * This routine provides a simple way to do a number of useful searches:
+ * * Find the nearest navaid on this frequency.
+ * * Find the nearest airport.
+ * * Find the VOR whose ID is "BOS".
+ * * Find the nearest airport whose name contains "Chicago".
+ *
+ */
+XPLM_API XPLMNavRef XPLMFindNavAid(
+                         const char *         inNameFragment,         /* Can be NULL */
+                         const char *         inIDFragment,           /* Can be NULL */
+                         float *              inLat,                  /* Can be NULL */
+                         float *              inLon,                  /* Can be NULL */
+                         int *                inFrequency,            /* Can be NULL */
+                         XPLMNavType          inType);
+
+/*
+ * XPLMGetNavAidInfo
+ * 
+ * This routine returns information about a navaid.  Any non-null field is
+ * filled out with information if it is available.
+ * 
+ * Frequencies are in the nav.dat convention as described in the X-Plane nav
+ * database FAQ: NDB frequencies are exact, all others are multiplied by 100.
+ * 
+ * The buffer for IDs should be at least 6 chars and the buffer for names
+ * should be at least 41 chars, but since these values are likely to go up, I
+ * recommend passing at least 32 chars for IDs and 256 chars for names when
+ * possible.
+ * 
+ * The outReg parameter tells if the navaid is within the local "region" of
+ * loaded DSFs.  (This information may not be particularly useful to plugins.)
+ * The parameter is a single byte value 1 for true or 0 for false, not a C
+ * string.
+ *
+ */
+XPLM_API void       XPLMGetNavAidInfo(
+                         XPLMNavRef           inRef,
+                         XPLMNavType *        outType,                /* Can be NULL */
+                         float *              outLatitude,            /* Can be NULL */
+                         float *              outLongitude,           /* Can be NULL */
+                         float *              outHeight,              /* Can be NULL */
+                         int *                outFrequency,           /* Can be NULL */
+                         float *              outHeading,             /* Can be NULL */
+                         char *               outID,                  /* Can be NULL */
+                         char *               outName,                /* Can be NULL */
+                         char *               outReg);                /* Can be NULL */
+
+/***************************************************************************
+ * FLIGHT MANAGEMENT COMPUTER
+ ***************************************************************************/
+/*
+ * Note: the FMS works based on an array of entries.  Indices into the array
+ * are zero-based.  Each entry is a navaid plus an altitude.  The FMS tracks
+ * the currently displayed entry and the entry that it is flying to.
+ * 
+ * The FMS must be programmed with contiguous entries, so clearing an entry at
+ * the end shortens the effective flight plan.  There is a max of 100
+ * waypoints in the flight plan.
+ *
+ */
+
+
+/*
+ * XPLMCountFMSEntries
+ * 
+ * This routine returns the number of entries in the FMS.
+ *
+ */
+XPLM_API int        XPLMCountFMSEntries(void);
+
+/*
+ * XPLMGetDisplayedFMSEntry
+ * 
+ * This routine returns the index of the entry the pilot is viewing.
+ *
+ */
+XPLM_API int        XPLMGetDisplayedFMSEntry(void);
+
+/*
+ * XPLMGetDestinationFMSEntry
+ * 
+ * This routine returns the index of the entry the FMS is flying to.
+ *
+ */
+XPLM_API int        XPLMGetDestinationFMSEntry(void);
+
+/*
+ * XPLMSetDisplayedFMSEntry
+ * 
+ * This routine changes which entry the FMS is showing to the index specified.
+ *
+ */
+XPLM_API void       XPLMSetDisplayedFMSEntry(
+                         int                  inIndex);
+
+/*
+ * XPLMSetDestinationFMSEntry
+ * 
+ * This routine changes which entry the FMS is flying the aircraft toward. The
+ * track is from the n-1'th point to the n'th point. 
+ *
+ */
+XPLM_API void       XPLMSetDestinationFMSEntry(
+                         int                  inIndex);
+
+/*
+ * XPLMGetFMSEntryInfo
+ * 
+ * This routine returns information about a given FMS entry. If the entry is
+ * an airport or navaid, a reference to a nav entry can be returned allowing
+ * you to find additional information (such as a frequency, ILS heading, name,
+ * etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the
+ * information has been looked up asynchronously, so after flightplan changes,
+ * it might take up to a second for this field to become populated. The other
+ * information is available immediately. For a lat/lon entry, the lat/lon is
+ * returned by this routine but the navaid cannot be looked up (and the
+ * reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at
+ * least 256 chars in length.
+ * 
+ * WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will
+ * not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead
+ * just remain the value of the variable that you passed the pointer to.
+ * Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before
+ * passing the pointer to this function.
+ *
+ */
+XPLM_API void       XPLMGetFMSEntryInfo(
+                         int                  inIndex,
+                         XPLMNavType *        outType,                /* Can be NULL */
+                         char *               outID,                  /* Can be NULL */
+                         XPLMNavRef *         outRef,                 /* Can be NULL */
+                         int *                outAltitude,            /* Can be NULL */
+                         float *              outLat,                 /* Can be NULL */
+                         float *              outLon);                /* Can be NULL */
+
+/*
+ * XPLMSetFMSEntryInfo
+ * 
+ * This routine changes an entry in the FMS to have the destination navaid
+ * passed in and the altitude specified.  Use this only for airports, fixes,
+ * and radio-beacon navaids.  Currently of radio beacons, the FMS can only
+ * support VORs and NDBs. Use the routines below to clear or fly to a lat/lon.
+ *
+ */
+XPLM_API void       XPLMSetFMSEntryInfo(
+                         int                  inIndex,
+                         XPLMNavRef           inRef,
+                         int                  inAltitude);
+
+/*
+ * XPLMSetFMSEntryLatLon
+ * 
+ * This routine changes the entry in the FMS to a lat/lon entry with the given
+ * coordinates.
+ *
+ */
+XPLM_API void       XPLMSetFMSEntryLatLon(
+                         int                  inIndex,
+                         float                inLat,
+                         float                inLon,
+                         int                  inAltitude);
+
+/*
+ * XPLMClearFMSEntry
+ * 
+ * This routine clears the given entry, potentially shortening the flight
+ * plan.
+ *
+ */
+XPLM_API void       XPLMClearFMSEntry(
+                         int                  inIndex);
+
+#if defined(XPLM410)
+/*
+ * XPLMNavFlightPlan
+ * 
+ *     These enumerations defines the flightplan you are accesing using the
+ *     FMSFlightPlan functions. An airplane can have up to two navigation
+ *     devices (GPS or FMS) and each device can have two flightplans. A GPS
+ *     has an enroute and an approach flightplan. An FMS has an active and a
+ *     temporary flightplan. If you are trying to access a flightplan that
+ *     doesn't exist in your aircraft, e.g. asking a GPS for a temp
+ *     flightplan, FMSFlighPlan functions have no effect and will return no
+ *     information.
+ *
+ */
+enum {
+    xplm_Fpl_Pilot_Primary                   = 0,
+
+    xplm_Fpl_CoPilot_Primary                 = 1,
+
+    xplm_Fpl_Pilot_Approach                  = 2,
+
+    xplm_Fpl_CoPilot_Approach                = 3,
+
+    xplm_Fpl_Pilot_Temporary                 = 4,
+
+    xplm_Fpl_CoPilot_Temporary               = 5,
+
+
+};
+typedef int XPLMNavFlightPlan;
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMCountFMSFlightPlanEntries
+ * 
+ * This routine returns the number of entries in the FMS.
+ *
+ */
+XPLM_API int        XPLMCountFMSFlightPlanEntries(
+                         XPLMNavFlightPlan    inFlightPlan);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetDisplayedFMSFlightPlanEntry
+ * 
+ * This routine returns the index of the entry the pilot is viewing.
+ *
+ */
+XPLM_API int        XPLMGetDisplayedFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetDestinationFMSFlightPlanEntry
+ * 
+ * This routine returns the index of the entry the FMS is flying to.
+ *
+ */
+XPLM_API int        XPLMGetDestinationFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetDisplayedFMSFlightPlanEntry
+ * 
+ * This routine changes which entry the FMS is showing to the index specified.
+ *
+ */
+XPLM_API void       XPLMSetDisplayedFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetDestinationFMSFlightPlanEntry
+ * 
+ * This routine changes which entry the FMS is flying the aircraft toward. The
+ * track is from the n-1'th point to the n'th point.
+ *
+ */
+XPLM_API void       XPLMSetDestinationFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetDirectToFMSFlightPlanEntry
+ * 
+ * This routine changes which entry the FMS is flying the aircraft toward. The
+ * track is from the current position of the aircraft directly to the n'th
+ * point, ignoring the point before it.
+ *
+ */
+XPLM_API void       XPLMSetDirectToFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMGetFMSFlightPlanEntryInfo
+ * 
+ * This routine returns information about a given FMS entry. If the entry is
+ * an airport or navaid, a reference to a nav entry can be returned allowing
+ * you to find additional information (such as a frequency, ILS heading, name,
+ * etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the
+ * information has been looked up asynchronously, so after flightplan changes,
+ * it might take up to a second for this field to become populated. The other
+ * information is available immediately. For a lat/lon entry, the lat/lon is
+ * returned by this routine but the navaid cannot be looked up (and the
+ * reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at
+ * least 256 chars in length.
+ * 
+ * WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will
+ * not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead
+ * just remain the value of the variable that you passed the pointer to.
+ * Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before
+ * passing the pointer to this function.
+ *
+ */
+XPLM_API void       XPLMGetFMSFlightPlanEntryInfo(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex,
+                         XPLMNavType *        outType,                /* Can be NULL */
+                         char *               outID,                  /* Can be NULL */
+                         XPLMNavRef *         outRef,                 /* Can be NULL */
+                         int *                outAltitude,            /* Can be NULL */
+                         float *              outLat,                 /* Can be NULL */
+                         float *              outLon);                /* Can be NULL */
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetFMSFlightPlanEntryInfo
+ * 
+ * This routine changes an entry in the FMS to have the destination navaid
+ * passed in and the altitude specified.  Use this only for airports, fixes,
+ * and radio-beacon navaids.  Currently of radio beacons, the FMS can only
+ * support VORs, NDBs and TACANs. Use the routines below to clear or fly to a
+ * lat/lon.
+ *
+ */
+XPLM_API void       XPLMSetFMSFlightPlanEntryInfo(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex,
+                         XPLMNavRef           inRef,
+                         int                  inAltitude);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetFMSFlightPlanEntryLatLon
+ * 
+ * This routine changes the entry in the FMS to a lat/lon entry with the given
+ * coordinates.
+ *
+ */
+XPLM_API void       XPLMSetFMSFlightPlanEntryLatLon(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex,
+                         float                inLat,
+                         float                inLon,
+                         int                  inAltitude);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSetFMSFlightPlanEntryLatLonWithId
+ * 
+ * This routine changes the entry in the FMS to a lat/lon entry with the given
+ * coordinates. You can specify the display ID of the waypoint.
+ *
+ */
+XPLM_API void       XPLMSetFMSFlightPlanEntryLatLonWithId(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex,
+                         float                inLat,
+                         float                inLon,
+                         int                  inAltitude,
+                         const char*          inId,
+                         unsigned int         inIdLength);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMClearFMSFlightPlanEntry
+ * 
+ * This routine clears the given entry, potentially shortening the flight
+ * plan.
+ *
+ */
+XPLM_API void       XPLMClearFMSFlightPlanEntry(
+                         XPLMNavFlightPlan    inFlightPlan,
+                         int                  inIndex);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMLoadFMSFlightPlan
+ * 
+ * Loads an X-Plane 11 and later formatted flightplan from the buffer into the
+ * FMS or GPS, including instrument procedures. Use device index 0 for the
+ * pilot-side and device index 1 for the co-pilot side unit.
+ *
+ */
+XPLM_API void       XPLMLoadFMSFlightPlan(
+                         int                  inDevice,
+                         const char *         inBuffer,
+                         unsigned int         inBufferLen);
+#endif /* XPLM410 */
+
+#if defined(XPLM410)
+/*
+ * XPLMSaveFMSFlightPlan
+ * 
+ * Saves an X-Plane 11 formatted flightplan from the FMS or GPS into a char
+ * buffer that you provide. Use device index 0 for the pilot-side and device
+ * index 1 for the co-pilot side unit. Provide the length of the buffer you
+ * allocated. X-Plane will write a null-terminated string if the full flight
+ * plan fits into the buffer. If your buffer is too small, X-Plane will write
+ * inBufferLen characters, and the resulting buffer is not null-terminated. 
+ * The return value is the number of characters (including null terminator)
+ * that X-Plane needed to write the flightplan. If this number is larger than
+ * the buffer you provided, the flightplan in the buffer will be incomplete
+ * and the buffer not null-terminated.
+ *
+ */
+XPLM_API unsigned int XPLMSaveFMSFlightPlan(
+                         int                  inDevice,
+                         char *               inBuffer,
+                         unsigned int         inBufferLen);
+#endif /* XPLM410 */
+
+/***************************************************************************
+ * GPS RECEIVER
+ ***************************************************************************/
+/*
+ * These APIs let you read data from the GPS unit.
+ *
+ */
+
+/*
+ * XPLMGetGPSDestinationType
+ * 
+ * This routine returns the type of the currently selected GPS destination,
+ * one of fix, airport, VOR or NDB.
+ *
+ */
+XPLM_API XPLMNavType XPLMGetGPSDestinationType(void);
+
+/*
+ * XPLMGetGPSDestination
+ * 
+ * This routine returns the current GPS destination.
+ *
+ */
+XPLM_API XPLMNavRef XPLMGetGPSDestination(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMPlanes.h b/SDK/CHeaders/XPLM/XPLMPlanes.h
new file mode 100644
index 0000000..bd5b84d
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMPlanes.h
@@ -0,0 +1,287 @@
+#ifndef _XPLMPlanes_h_
+#define _XPLMPlanes_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMPlanes
+ ***************************************************************************/
+/*
+ * The XPLMPlanes APIs allow you to control the various aircraft in X-Plane,
+ * both the user's and the sim's.
+ * 
+ * *Note*: unlike almost all other APIs in the SDK, aircraft paths are _full_
+ *  file system paths for historical reasons. You'll need to prefix all
+ *  relative paths with the X-Plane path as accessed via XPLMGetSystemPath.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * USER AIRCRAFT ACCESS
+ ***************************************************************************/
+
+/*
+ * XPLMSetUsersAircraft
+ * 
+ * This routine changes the user's aircraft.  Note that this will reinitialize
+ * the user to be on the nearest airport's first runway.  Pass in a full path
+ * (hard drive and everything including the .acf extension) to the .acf file.
+ *
+ */
+XPLM_API void       XPLMSetUsersAircraft(
+                         const char *         inAircraftPath);
+/*
+ * XPLMPlaceUserAtAirport
+ * 
+ * This routine places the user at a given airport.  Specify the airport by
+ * its X-Plane airport ID (e.g. 'KBOS').
+ *
+ */
+XPLM_API void       XPLMPlaceUserAtAirport(
+                         const char *         inAirportCode);
+#if defined(XPLM300)
+/*
+ * XPLMPlaceUserAtLocation
+ * 
+ * Places the user at a specific location after performing any necessary
+ * scenery loads.
+ * 
+ * As with in-air starts initiated from the X-Plane user interface, the
+ * aircraft will always start with its engines running, regardless of the
+ * user's preferences (i.e., regardless of what the dataref
+ * `sim/operation/prefs/startup_running` says).
+ *
+ */
+XPLM_API void       XPLMPlaceUserAtLocation(
+                         double               latitudeDegrees,
+                         double               longitudeDegrees,
+                         float                elevationMetersMSL,
+                         float                headingDegreesTrue,
+                         float                speedMetersPerSecond);
+#endif /* XPLM300 */
+/***************************************************************************
+ * GLOBAL AIRCRAFT ACCESS
+ ***************************************************************************/
+
+/* The user's aircraft is always index 0.                                     */
+#define XPLM_USER_AIRCRAFT   0
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMPlaneDrawState_t
+ * 
+ * This structure contains additional plane parameter info to be passed to
+ * draw plane.  Make sure to fill in the size of the structure field with
+ * sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you
+ * knew about when compiling your plugin (since more fields may be added
+ * later).
+ * 
+ * Most of these fields are ratios from 0 to 1 for control input.  X-Plane
+ * calculates what the actual controls look like based on the .acf file for
+ * that airplane.  Note for the yoke inputs, this is what the pilot of the
+ * plane has commanded (post artificial stability system if there were one)
+ * and affects ailerons, rudder, etc.  It is not necessarily related to the
+ * actual position of the plane's surfaces!
+ *
+ */
+typedef struct {
+    /* The size of the draw state struct.                                         */
+     int                       structSize;
+    /* A ratio from [0..1] describing how far the landing gear is extended.       */
+     float                     gearPosition;
+    /* Ratio of flap deployment, 0 = up, 1 = full deploy.                         */
+     float                     flapRatio;
+    /* Ratio of spoiler deployment, 0 = none, 1 = full deploy.                    */
+     float                     spoilerRatio;
+    /* Ratio of speed brake deployment, 0 = none, 1 = full deploy.                */
+     float                     speedBrakeRatio;
+    /* Ratio of slat deployment, 0 = none, 1 = full deploy.                       */
+     float                     slatRatio;
+    /* Wing sweep ratio, 0 = forward, 1 = swept.                                  */
+     float                     wingSweep;
+    /* Thrust power, 0 = none, 1 = full fwd, -1 = full reverse.                   */
+     float                     thrust;
+    /* Total pitch input for this plane.                                          */
+     float                     yokePitch;
+    /* Total Heading input for this plane.                                        */
+     float                     yokeHeading;
+    /* Total Roll input for this plane.                                           */
+     float                     yokeRoll;
+} XPLMPlaneDrawState_t;
+#endif /* XPLM_DEPRECATED */
+/*
+ * XPLMCountAircraft
+ * 
+ * This function returns the number of aircraft X-Plane is capable of having,
+ * as well as the number of aircraft that are currently active.  These numbers
+ * count the user's aircraft.  It can also return the plugin that is currently
+ * controlling aircraft.  In X-Plane 7, this routine reflects the number of
+ * aircraft the user has enabled in the rendering options window.
+ *
+ */
+XPLM_API void       XPLMCountAircraft(
+                         int *                outTotalAircraft,
+                         int *                outActiveAircraft,
+                         XPLMPluginID *       outController);
+/*
+ * XPLMGetNthAircraftModel
+ * 
+ * This function returns the aircraft model for the Nth aircraft.  Indices are
+ * zero based, with zero being the user's aircraft.  The file name should be
+ * at least 256 chars in length; the path should be at least 512 chars in
+ * length.
+ *
+ */
+XPLM_API void       XPLMGetNthAircraftModel(
+                         int                  inIndex,
+                         char *               outFileName,
+                         char *               outPath);
+/***************************************************************************
+ * EXCLUSIVE AIRCRAFT ACCESS
+ ***************************************************************************/
+/*
+ * The following routines require exclusive access to the airplane APIs. Only
+ * one plugin may have this access at a time.
+ *
+ */
+
+
+/*
+ * XPLMPlanesAvailable_f
+ * 
+ * Your airplanes available callback is called when another plugin gives up
+ * access to the multiplayer planes.  Use this to wait for access to
+ * multiplayer.
+ *
+ */
+typedef void (* XPLMPlanesAvailable_f)(
+                         void *               inRefcon);
+
+/*
+ * XPLMAcquirePlanes
+ * 
+ * XPLMAcquirePlanes grants your plugin exclusive access to the aircraft.  It
+ * returns 1 if you gain access, 0 if you do not.
+ * 
+ * inAircraft - pass in an array of pointers to strings specifying the planes
+ * you want loaded.  For any plane index you do not want loaded, pass a
+ * 0-length string.  Other strings should be full paths with the .acf
+ * extension.  NULL terminates this array, or pass NULL if there are no planes
+ * you want loaded.
+ * 
+ * If you pass in a callback and do not receive access to the planes your
+ * callback will be called when the airplanes are available. If you do receive
+ * airplane access, your callback will not be called.
+ *
+ */
+XPLM_API int        XPLMAcquirePlanes(
+                         char **              inAircraft,             /* Can be NULL */
+                         XPLMPlanesAvailable_f inCallback,
+                         void *               inRefcon);
+
+/*
+ * XPLMReleasePlanes
+ * 
+ * Call this function to release access to the planes.  Note that if you are
+ * disabled, access to planes is released for you and you must reacquire it.
+ *
+ */
+XPLM_API void       XPLMReleasePlanes(void);
+
+/*
+ * XPLMSetActiveAircraftCount
+ * 
+ * This routine sets the number of active planes.  If you pass in a number
+ * higher than the total number of planes availables, only the total number of
+ * planes available is actually used.
+ *
+ */
+XPLM_API void       XPLMSetActiveAircraftCount(
+                         int                  inCount);
+
+/*
+ * XPLMSetAircraftModel
+ * 
+ * This routine loads an aircraft model.  It may only be called if you have
+ * exclusive access to the airplane APIs.  Pass in the path of the model with
+ * the .acf extension.  The index is zero based, but you may not pass in 0
+ * (use XPLMSetUsersAircraft to load the user's aircracft).
+ *
+ */
+XPLM_API void       XPLMSetAircraftModel(
+                         int                  inIndex,
+                         const char *         inAircraftPath);
+
+/*
+ * XPLMDisableAIForPlane
+ * 
+ * This routine turns off X-Plane's AI for a given plane.  The plane will
+ * continue to draw and be a real plane in X-Plane, but will not move itself.
+ *
+ */
+XPLM_API void       XPLMDisableAIForPlane(
+                         int                  inPlaneIndex);
+
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMDrawAircraft
+ * 
+ * WARNING: Aircraft drawing via this API is deprecated and WILL NOT WORK in
+ * future versions of X-Plane.  Use XPLMInstance for 3-d drawing of custom
+ * aircraft models.
+ * 
+ * This routine draws an aircraft.  It can only be called from a 3-d drawing
+ * callback.  Pass in the position of the plane in OpenGL local coordinates
+ * and the orientation of the plane.  A 1 for full drawing indicates that the
+ * whole plane must be drawn; a 0 indicates you only need the nav lights
+ * drawn. (This saves rendering time when planes are far away.)
+ *
+ */
+XPLM_API void       XPLMDrawAircraft(
+                         int                  inPlaneIndex,
+                         float                inX,
+                         float                inY,
+                         float                inZ,
+                         float                inPitch,
+                         float                inRoll,
+                         float                inYaw,
+                         int                  inFullDraw,
+                         XPLMPlaneDrawState_t * inDrawStateInfo);
+#endif /* XPLM_DEPRECATED */
+
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMReinitUsersPlane
+ * 
+ * WARNING: DO NOT USE.  Use XPLMPlaceUserAtAirport or
+ * XPLMPlaceUserAtLocation.
+ * 
+ * This function recomputes the derived flight model data from the aircraft
+ * structure in memory.  If you have used the data access layer to modify the
+ * aircraft structure, use this routine to resynchronize X-Plane; since
+ * X-Plane works at least partly from derived values, the sim will not behave
+ * properly until this is called.
+ * 
+ * WARNING: this routine does not necessarily place the airplane at the
+ * airport; use XPLMSetUsersAircraft to be compatible.  This routine is
+ * provided to do special experimentation with flight models without resetting
+ * flight.
+ *
+ */
+XPLM_API void       XPLMReinitUsersPlane(void);
+#endif /* XPLM_DEPRECATED */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMPlugin.h b/SDK/CHeaders/XPLM/XPLMPlugin.h
new file mode 100644
index 0000000..da84ac8
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMPlugin.h
@@ -0,0 +1,456 @@
+#ifndef _XPLMPlugin_h_
+#define _XPLMPlugin_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMPlugin
+ ***************************************************************************/
+/*
+ * These APIs provide facilities to find and work with other plugins and
+ * manage other plugins.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * FINDING PLUGINS
+ ***************************************************************************/
+/*
+ * These APIs allow you to find another plugin or yourself, or iterate across
+ * all plugins.  For example, if you wrote an FMS plugin that needed to talk
+ * to an autopilot plugin, you could use these APIs to locate the autopilot
+ * plugin.
+ *
+ */
+
+
+/*
+ * XPLMGetMyID
+ * 
+ * This routine returns the plugin ID of the calling plug-in.  Call this to
+ * get your own ID.
+ *
+ */
+XPLM_API XPLMPluginID XPLMGetMyID(void);
+
+/*
+ * XPLMCountPlugins
+ * 
+ * This routine returns the total number of plug-ins that are loaded, both
+ * disabled and enabled.
+ *
+ */
+XPLM_API int        XPLMCountPlugins(void);
+
+/*
+ * XPLMGetNthPlugin
+ * 
+ * This routine returns the ID of a plug-in by index.  Index is 0 based from 0
+ * to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary
+ * order.
+ *
+ */
+XPLM_API XPLMPluginID XPLMGetNthPlugin(
+                         int                  inIndex);
+
+/*
+ * XPLMFindPluginByPath
+ * 
+ * This routine returns the plug-in ID of the plug-in whose file exists at the
+ * passed in absolute file system path.  XPLM_NO_PLUGIN_ID is returned if the
+ * path does not point to a currently loaded plug-in.
+ *
+ */
+XPLM_API XPLMPluginID XPLMFindPluginByPath(
+                         const char *         inPath);
+
+/*
+ * XPLMFindPluginBySignature
+ * 
+ * This routine returns the plug-in ID of the plug-in whose signature matches
+ * what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this
+ * signature.  Signatures are the best way to identify another plug-in as they
+ * are independent of the file system path of a plug-in or the human-readable
+ * plug-in name, and should be unique for all plug-ins.  Use this routine to
+ * locate another plugin that your plugin interoperates with
+ *
+ */
+XPLM_API XPLMPluginID XPLMFindPluginBySignature(
+                         const char *         inSignature);
+
+/*
+ * XPLMGetPluginInfo
+ * 
+ * This routine returns information about a plug-in.  Each parameter should be
+ * a pointer to a buffer of at least
+ * 256 characters, or NULL to not receive the information.
+ * 
+ * outName - the human-readable name of the plug-in. outFilePath - the
+ * absolute file path to the file that contains this plug-in. outSignature - a
+ * unique string that identifies this plug-in. outDescription - a
+ * human-readable description of this plug-in.
+ *
+ */
+XPLM_API void       XPLMGetPluginInfo(
+                         XPLMPluginID         inPlugin,
+                         char *               outName,                /* Can be NULL */
+                         char *               outFilePath,            /* Can be NULL */
+                         char *               outSignature,           /* Can be NULL */
+                         char *               outDescription);        /* Can be NULL */
+
+/***************************************************************************
+ * ENABLING/DISABLING PLUG-INS
+ ***************************************************************************/
+/*
+ * These routines are used to work with plug-ins and manage them.  Most
+ * plugins will not need to use these APIs.
+ *
+ */
+
+
+/*
+ * XPLMIsPluginEnabled
+ * 
+ * Returns whether the specified plug-in is enabled for running.
+ *
+ */
+XPLM_API int        XPLMIsPluginEnabled(
+                         XPLMPluginID         inPluginID);
+
+/*
+ * XPLMEnablePlugin
+ * 
+ * This routine enables a plug-in if it is not already enabled. It returns 1
+ * if the plugin was enabled or successfully enables itself, 0 if it does not.
+ * Plugins may fail to enable (for example, if resources cannot be acquired)
+ * by returning 0 from their XPluginEnable callback.
+ *
+ */
+XPLM_API int        XPLMEnablePlugin(
+                         XPLMPluginID         inPluginID);
+
+/*
+ * XPLMDisablePlugin
+ * 
+ * This routine disableds an enabled plug-in.
+ *
+ */
+XPLM_API void       XPLMDisablePlugin(
+                         XPLMPluginID         inPluginID);
+
+/*
+ * XPLMReloadPlugins
+ * 
+ * This routine reloads all plug-ins.  Once this routine is called and you
+ * return from the callback you were within (e.g. a menu select callback) you
+ * will receive your XPluginDisable and XPluginStop callbacks and your DLL
+ * will be unloaded, then the start process happens as if the sim was starting
+ * up.
+ *
+ */
+XPLM_API void       XPLMReloadPlugins(void);
+
+/***************************************************************************
+ * INTERPLUGIN MESSAGING
+ ***************************************************************************/
+/*
+ * Plugin messages are defined as 32-bit integers.  Messages below 0x00FFFFFF
+ * are reserved for X-Plane and the plugin SDK.
+ * 
+ * Messages come with a pointer parameter; the meaning of this pointer depends
+ * on the message itself. In some messages, the pointer parameter  contains an
+ * actual typed pointer to data that can be inspected in the plugin; in these
+ * cases the documentation will state that the parameter "points to"
+ * information.
+ * 
+ * in other cases, the value of the pointer is actually an integral number
+ * stuffed into the pointer's storage. In these second cases, the pointer
+ * parameter needs to be cast, not dereferenced. In these caess, the
+ * documentation will state that the parameter "contains" a value, which will
+ * always be an integral type.
+ * 
+ * Some messages don't use the pointer parameter - in this case your plugin
+ * should ignore it.
+ * 
+ * Messages have two conceptual uses: notifications and commands.  Commands
+ * are sent from one plugin to another to induce behavior; notifications are
+ * sent from one plugin to all others for informational purposes.  It is
+ * important that commands and notifications not have the same values because
+ * this could cause a notification sent by one plugin to accidentally induce a
+ * command in another.
+ * 
+ * By convention, plugin-defined notifications should have the high bit set
+ * (e.g. be greater or equal to unsigned 0x8000000) while commands should have
+ * this bit be cleared.
+ * 
+ * The following messages are sent to your plugin by X-Plane.
+ *
+ */
+
+
+/* This message is sent to your plugin whenever the user's plane crashes. The *
+ * parameter is ignored.                                                      */
+#define XPLM_MSG_PLANE_CRASHED 101
+
+/* This message is sent to your plugin whenever a new plane is loaded.  The   *
+ * parameter contains the index number of the plane being loaded; 0 indicates *
+ * the user's plane.                                                          */
+#define XPLM_MSG_PLANE_LOADED 102
+
+/* This messages is sent whenever the user's plane is positioned at a new     *
+ * airport. The parameter is ignored.                                         */
+#define XPLM_MSG_AIRPORT_LOADED 103
+
+/* This message is sent whenever new scenery is loaded.  Use datarefs to      *
+ * determine the new scenery files that were loaded. The parameter is ignored.*/
+#define XPLM_MSG_SCENERY_LOADED 104
+
+/* This message is sent whenever the user adjusts the number of X-Plane       *
+ * aircraft models.  You must use XPLMCountPlanes to find out how many planes *
+ * are now available.  This message will only be sent in XP7 and higher       *
+ * because in XP6 the number of aircraft is not user-adjustable. The parameter*
+ * is ignored.                                                                */
+#define XPLM_MSG_AIRPLANE_COUNT_CHANGED 105
+
+#if defined(XPLM200)
+/* This message is sent to your plugin whenever a plane is unloaded.  The     *
+ * parameter contains the index number of the plane being unloaded; 0         *
+ * indicates the user's plane.  The parameter is of type int, passed as the   *
+ * value of the pointer.  (That is: the parameter is an int, not a pointer to *
+ * an int.)                                                                   */
+#define XPLM_MSG_PLANE_UNLOADED 106
+#endif /* XPLM200 */
+
+#if defined(XPLM210)
+/* This message is sent to your plugin right before X-Plane writes its        *
+ * preferences file.  You can use this for two purposes: to write your own    *
+ * preferences, and to modify any datarefs to influence preferences output.   *
+ * For example, if your plugin temporarily modifies saved preferences, you can*
+ * put them back to their default values here to avoid having the tweaks be   *
+ * persisted if your plugin is not loaded on the next invocation of X-Plane.  *
+ * The parameter is ignored.                                                  */
+#define XPLM_MSG_WILL_WRITE_PREFS 107
+#endif /* XPLM210 */
+
+#if defined(XPLM210)
+/* This message is sent to your plugin right after a livery is loaded for an  *
+ * airplane.  You can use this to check the new livery (via datarefs) and     *
+ * react accordingly.  The parameter contains the index number of the aircraft*
+ * whose livery is changing.                                                  */
+#define XPLM_MSG_LIVERY_LOADED 108
+#endif /* XPLM210 */
+
+#if defined(XPLM301)
+/* Sent to your plugin right before X-Plane enters virtual reality mode (at   *
+ * which time any windows that are not positioned in VR mode will no longer be*
+ * visible to the user). The parameter is unused and should be ignored.       */
+#define XPLM_MSG_ENTERED_VR  109
+#endif /* XPLM301 */
+
+#if defined(XPLM301)
+/* Sent to your plugin right before X-Plane leaves virtual reality mode (at   *
+ * which time you may want to clean up windows that are positioned in VR      *
+ * mode). The parameter is unused and should be ignored.                      */
+#define XPLM_MSG_EXITING_VR  110
+#endif /* XPLM301 */
+
+#if defined(XPLM303)
+/* Sent to your plugin if another plugin wants to take over AI planes. If you *
+ * are a synthetic traffic provider,  that probably means a plugin for an     *
+ * online network has connected and wants to supply aircraft flown by real    *
+ * humans and you should cease to provide synthetic traffic. If however you   *
+ * are providing online traffic from real humans,  you probably don't want to *
+ * disconnect, in which case you just ignore this message. The sender is the  *
+ * plugin ID of the plugin asking for control of the planes now. You can use  *
+ * it to find out who is requesting and whether you should yield to them.     *
+ * Synthetic traffic providers should always yield to online networks. The    *
+ * parameter is unused and should be ignored.                                 */
+#define XPLM_MSG_RELEASE_PLANES 111
+#endif /* XPLM303 */
+
+#if defined(XPLM400)
+/* Sent to your plugin after FMOD sound banks are loaded. The parameter is the*
+ * XPLMBankID enum in XPLMSound.h, 0 for the master bank and 1 for the radio  *
+ * bank.                                                                      */
+#define XPLM_MSG_FMOD_BANK_LOADED 112
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/* Sent to your plugin before FMOD sound banks are unloaded. Any associated   *
+ * resources should be cleaned up at this point. The parameter is the         *
+ * XPLMBankID enum in XPLMSound.h, 0 for the master bank and 1 for the radio  *
+ * bank.                                                                      */
+#define XPLM_MSG_FMOD_BANK_UNLOADING 113
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/* Sent to your plugin per-frame (at-most) when/if datarefs are added. It will*
+ * include the new data ref total count so that your plugin can keep a local  *
+ * cache of the total, see what's changed and know which ones to inquire about*
+ * if it cares.                                                               *
+ *                                                                            *
+ * This message is only sent to plugins that enable the                       *
+ * XPLM_WANTS_DATAREF_NOTIFICATIONS feature.                                  */
+#define XPLM_MSG_DATAREFS_ADDED 114
+#endif /* XPLM400 */
+
+/*
+ * XPLMSendMessageToPlugin
+ * 
+ * This function sends a message to another plug-in or X-Plane.  Pass
+ * XPLM_NO_PLUGIN_ID to broadcast to all plug-ins.  Only enabled plug-ins with
+ * a message receive function receive the message.
+ *
+ */
+XPLM_API void       XPLMSendMessageToPlugin(
+                         XPLMPluginID         inPlugin,
+                         int                  inMessage,
+                         void *               inParam);
+
+#if defined(XPLM200)
+/***************************************************************************
+ * Plugin Features API
+ ***************************************************************************/
+/*
+ * The plugin features API allows your plugin to "sign up" for additional
+ * capabilities and plugin system features that are normally disabled for
+ * backward compatibility or performance.  This allows advanced plugins to
+ * "opt-in"  to new behavior.
+ * 
+ * Each feature is defined by a permanent string name.  The feature string
+ * names will vary with the particular installation of X-Plane, so plugins
+ * should not expect a feature to be guaranteed present.
+ * 
+ * XPLM_WANTS_REFLECTIONS
+ * ----------------------
+ * 
+ * Available in the SDK 2.0 and later for X-Plane 9, enabling this capability
+ * causes your plugin to receive drawing hook callbacks when X-Plane builds
+ * its off-screen reflection and shadow rendering passes. Plugins should
+ * enable this and examine the dataref sim/graphics/view/plane_render_type to
+ * determine whether the drawing callback is for a reflection, shadow
+ * calculation, or the main screen. Rendering can be simlified or omitted for
+ * reflections, and non-solid drawing should be skipped for shadow
+ * calculations.
+ * 
+ * **Note**: direct drawing via draw callbacks is not recommended; use the
+ *   XPLMInstance API to create object models instead.
+ * 
+ * XPLM_USE_NATIVE_PATHS
+ * ---------------------
+ * 
+ * available in the SDK 2.1 and later for X-Plane 10, this modifies the plugin
+ * system to use Unix-style paths on all operating systems. With this enabled:
+ * 
+ * * OS X paths will match the native OS X Unix.
+ * * Windows will use forward slashes but preserve C:\ or another drive letter
+ *   when using complete file paths.
+ * * Linux uses its native file system path scheme.
+ * 
+ * Without this enabled:
+ * 
+ * * OS X will use CFM file paths separated by a colon.
+ * * Windows will use back-slashes and conventional DOS paths.
+ * * Linux uses its native file system path scheme.
+ * 
+ * All plugins should enable this feature on OS X to access the native file
+ * system.
+ * 
+ * XPLM_USE_NATIVE_WIDGET_WINDOWS
+ * ------------------------------
+ * 
+ * Available in the SDK 3.0.2 SDK, this capability tells the widgets library
+ * to use new, modern X-Plane backed XPLMDisplay windows to anchor all widget
+ * trees.  Without it, widgets will always use legacy windows.
+ * 
+ * Plugins should enable this to allow their widget hierarchies to respond to
+ * the user's UI size settings and to map widget-based windwos to a VR HMD.
+ * 
+ * Before enabling this, make sure any custom widget code in your plugin is
+ * prepared to cope with the UI coordinate system not being th same as the
+ * OpenGL window coordinate system.
+ * 
+ * XPLM_WANTS_DATAREF_NOTIFICATIONS
+ * --------------------------------
+ * 
+ * Available in the SDK 4.0.0, this capability tells X-Plane to to send the
+ * enabling plugin the new XPLM_MSG_DATAREFS_ADDED message any time new
+ * datarefs are added. The SDK will coalesce consecutive dataref registrations
+ * to minimize the number of messages sent.
+ *
+ */
+
+
+/*
+ * XPLMFeatureEnumerator_f
+ * 
+ * You pass an XPLMFeatureEnumerator_f to get a list of all features supported
+ * by a given version running version of X-Plane.  This routine is called once
+ * for each feature.
+ *
+ */
+typedef void (* XPLMFeatureEnumerator_f)(
+                         const char *         inFeature,
+                         void *               inRef);
+
+/*
+ * XPLMHasFeature
+ * 
+ * This returns 1 if the given installation of X-Plane supports a feature, or
+ * 0 if it does not.
+ *
+ */
+XPLM_API int        XPLMHasFeature(
+                         const char *         inFeature);
+
+/*
+ * XPLMIsFeatureEnabled
+ * 
+ * This returns 1 if a feature is currently enabled for your plugin, or 0 if
+ * it is not enabled.  It is an error to call this routine with an unsupported
+ * feature.
+ *
+ */
+XPLM_API int        XPLMIsFeatureEnabled(
+                         const char *         inFeature);
+
+/*
+ * XPLMEnableFeature
+ * 
+ * This routine enables or disables a feature for your plugin.  This will
+ * change the running behavior of X-Plane and your plugin in some way,
+ * depending on the feature.
+ *
+ */
+XPLM_API void       XPLMEnableFeature(
+                         const char *         inFeature,
+                         int                  inEnable);
+
+/*
+ * XPLMEnumerateFeatures
+ * 
+ * This routine calls your enumerator callback once for each feature that this
+ * running version of X-Plane supports. Use this routine to determine all of
+ * the features that X-Plane can support.
+ *
+ */
+XPLM_API void       XPLMEnumerateFeatures(
+                         XPLMFeatureEnumerator_f inEnumerator,
+                         void *               inRef);
+
+#endif /* XPLM200 */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMProcessing.h b/SDK/CHeaders/XPLM/XPLMProcessing.h
new file mode 100644
index 0000000..247e71e
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMProcessing.h
@@ -0,0 +1,267 @@
+#ifndef _XPLMProcessing_h_
+#define _XPLMProcessing_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMProcessing
+ ***************************************************************************/
+/*
+ * This API allows you to get regular callbacks during the flight loop, the
+ * part of X-Plane where the plane's position calculates the physics of
+ * flight, etc. Use these APIs to accomplish periodic tasks like logging data
+ * and performing I/O.
+ * 
+ * You can receive a callback either just before or just after the per-frame
+ * physics calculations happen - you can use post-flightmodel callbacks to
+ * "patch" the flight model after it has run.
+ * 
+ * If the user has set the number of flight model iterations per frame greater
+ * than one your plugin will _not_ see this; these integrations run on the
+ * sub-section of the flight model where iterations improve responsiveness
+ * (e.g. physical integration, not simple systems tracking) and are thus
+ * opaque to plugins.
+ * 
+ * Flight loop scheduling, when scheduled by time, is scheduled by a "first
+ * callback after the deadline" schedule, e.g. your callbacks will always be
+ * slightly late to ensure that we don't run faster than your deadline.
+ * 
+ * WARNING: Do NOT use these callbacks to draw! You cannot draw during flight
+ * loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info)
+ * for graphics or the XPLMInstance functions for aircraft or models. (One
+ * exception: you can use a post-flight loop callback to update your own
+ * off-screen FBOs.)
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * FLIGHT LOOP CALLBACKS
+ ***************************************************************************/
+
+#if defined(XPLM210)
+/*
+ * XPLMFlightLoopPhaseType
+ * 
+ * You can register a flight loop callback to run either before or after the
+ * flight model is integrated by X-Plane.
+ *
+ */
+enum {
+    /* Your callback runs before X-Plane integrates the flight model.             */
+    xplm_FlightLoop_Phase_BeforeFlightModel  = 0,
+
+    /* Your callback runs after X-Plane integrates the flight model.              */
+    xplm_FlightLoop_Phase_AfterFlightModel   = 1,
+
+
+};
+typedef int XPLMFlightLoopPhaseType;
+#endif /* XPLM210 */
+
+#if defined(XPLM210)
+/*
+ * XPLMFlightLoopID
+ * 
+ * This is an opaque identifier for a flight loop callback. You can use this
+ * identifier to easily track and remove your callbacks, or to use the new
+ * flight loop APIs.
+ *
+ */
+typedef void * XPLMFlightLoopID;
+#endif /* XPLM210 */
+
+/*
+ * XPLMFlightLoop_f
+ * 
+ * This is your flight loop callback. Each time the flight loop is iterated
+ * through, you receive this call at the end.
+ * 
+ * Flight loop callbacks receive a number of input timing parameters. These
+ * input timing parameters are not particularly useful; you may need to track
+ * your own timing data (e.g. by reading datarefs). The input parameters are:
+ * 
+ * - inElapsedSinceLastCall: the wall time since your last callback.
+ * - inElapsedTimeSinceLastFlightLoop: the wall time since any flight loop was
+ *   dispatched.
+ * - inCounter: a monotonically increasing counter, bumped once per flight
+ *   loop dispatch from the sim.
+ * - inRefcon: your own pointer constant provided when you registered yor
+ *   callback.
+ * 
+ * Your return value controls when you will next be called.
+ * 
+ *  - Return 0 to stop receiving callbacks.
+ *  - Return a positive number to specify how many seconds until the next
+ *    callback. (You will be called at or after this time, not before.)
+ *  - Return a negative number to specify how many loops must go by until you
+ *    are called. For example, -1.0 means call me the very next loop.
+ * 
+ * Try to run your flight loop as infrequently as is practical, and suspend it
+ * (using return value 0) when you do not need it; lots of flight loop
+ * callbacks that do nothing lowers X-Plane's frame rate.
+ * 
+ * Your callback will NOT be unregistered if you return 0; it will merely be
+ * inactive.
+ *
+ */
+typedef float (* XPLMFlightLoop_f)(
+                         float                inElapsedSinceLastCall,
+                         float                inElapsedTimeSinceLastFlightLoop,
+                         int                  inCounter,
+                         void *               inRefcon);
+
+#if defined(XPLM210)
+/*
+ * XPLMCreateFlightLoop_t
+ * 
+ * XPLMCreateFlightLoop_t contains the parameters to create a new flight loop
+ * callback. The structure may be expanded in future SDKs - always set
+ * structSize to the size of your structure in bytes.
+ *
+ */
+typedef struct {
+     int                       structSize;
+     XPLMFlightLoopPhaseType   phase;
+     XPLMFlightLoop_f          callbackFunc;
+     void *                    refcon;
+} XPLMCreateFlightLoop_t;
+#endif /* XPLM210 */
+
+/*
+ * XPLMGetElapsedTime
+ * 
+ * This routine returns the elapsed time since the sim started up in decimal
+ * seconds. This is a wall timer; it keeps counting upward even if the sim is
+ * pasued.
+ * 
+ * __WARNING__: XPLMGetElapsedTime is not a very good timer!  It lacks
+ * precision in both its data type and its source.  Do not attempt to use it
+ * for timing critical applications like network multiplayer.
+ *
+ */
+XPLM_API float      XPLMGetElapsedTime(void);
+
+/*
+ * XPLMGetCycleNumber
+ * 
+ * This routine returns a counter starting at zero for each sim cycle
+ * computed/video frame rendered.
+ *
+ */
+XPLM_API int        XPLMGetCycleNumber(void);
+
+/*
+ * XPLMRegisterFlightLoopCallback
+ * 
+ * This routine registers your flight loop callback. Pass in a pointer to a
+ * flight loop function and a refcon (an optional reference value determined
+ * by you). inInterval defines when you will be called. Pass in a positive
+ * number to specify seconds from registration time to the next callback. Pass
+ * in a negative number to indicate when you will be called (e.g. pass -1 to
+ * be called at the next cylcle). Pass 0 to not be called; your callback will
+ * be inactive.
+ * 
+ * (This legacy function only installs pre-flight-loop callbacks; use
+ * XPLMCreateFlightLoop for more control.)
+ *
+ */
+XPLM_API void       XPLMRegisterFlightLoopCallback(
+                         XPLMFlightLoop_f     inFlightLoop,
+                         float                inInterval,
+                         void *               inRefcon);
+
+/*
+ * XPLMUnregisterFlightLoopCallback
+ * 
+ * This routine unregisters your flight loop callback. Do NOT call it from
+ * your flight loop callback. Once your flight loop callback is unregistered,
+ * it will not be called again.
+ * 
+ * Only use this on flight loops registered via
+ * XPLMRegisterFlightLoopCallback.
+ *
+ */
+XPLM_API void       XPLMUnregisterFlightLoopCallback(
+                         XPLMFlightLoop_f     inFlightLoop,
+                         void *               inRefcon);
+
+/*
+ * XPLMSetFlightLoopCallbackInterval
+ * 
+ * This routine sets when a callback will be called. Do NOT call it from your
+ * callback; use the return value of the callback to change your callback
+ * interval from inside your callback.
+ * 
+ * inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback;
+ * positive for seconds, negative for cycles, and 0 for deactivating the
+ * callback. If inRelativeToNow is 1, times are from the time of this call;
+ * otherwise they are from the time the callback was last called (or the time
+ * it was registered if it has never been called.
+ *
+ */
+XPLM_API void       XPLMSetFlightLoopCallbackInterval(
+                         XPLMFlightLoop_f     inFlightLoop,
+                         float                inInterval,
+                         int                  inRelativeToNow,
+                         void *               inRefcon);
+
+#if defined(XPLM210)
+/*
+ * XPLMCreateFlightLoop
+ * 
+ * This routine creates a flight loop callback and returns its ID. The flight
+ * loop callback is created using the input param struct, and is inited to be
+ * unscheduled.
+ *
+ */
+XPLM_API XPLMFlightLoopID XPLMCreateFlightLoop(
+                         XPLMCreateFlightLoop_t * inParams);
+#endif /* XPLM210 */
+
+#if defined(XPLM210)
+/*
+ * XPLMDestroyFlightLoop
+ * 
+ * This routine destroys a flight loop callback by ID. Only call it on flight
+ * loops created with the newer XPLMCreateFlightLoop API.
+ *
+ */
+XPLM_API void       XPLMDestroyFlightLoop(
+                         XPLMFlightLoopID     inFlightLoopID);
+#endif /* XPLM210 */
+
+#if defined(XPLM210)
+/*
+ * XPLMScheduleFlightLoop
+ * 
+ * This routine schedules a flight loop callback for future execution. If
+ * inInterval is negative, it is run in a certain number of frames based on
+ * the absolute value of the input. If the interval is positive, it is a
+ * duration in seconds.
+ * 
+ * If inRelativeToNow is true, times are interpreted relative to the time this
+ * routine is called; otherwise they are relative to the last call time or the
+ * time the flight loop was registered (if never called).
+ *
+ */
+XPLM_API void       XPLMScheduleFlightLoop(
+                         XPLMFlightLoopID     inFlightLoopID,
+                         float                inInterval,
+                         int                  inRelativeToNow);
+#endif /* XPLM210 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMScenery.h b/SDK/CHeaders/XPLM/XPLMScenery.h
new file mode 100644
index 0000000..d15f83d
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMScenery.h
@@ -0,0 +1,450 @@
+#ifndef _XPLMScenery_h_
+#define _XPLMScenery_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMScenery
+ ***************************************************************************/
+/*
+ * This package contains APIs to interact with X-Plane's scenery system.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(XPLM200)
+/***************************************************************************
+ * Terrain Y-Testing
+ ***************************************************************************/
+/*
+ * The Y-testing API allows you to locate the physical scenery mesh. This
+ * would be used to place dynamic graphics on top of the ground in a plausible
+ * way or do physics interactions.
+ * 
+ * The Y-test API works via probe objects, which are allocated by your plugin
+ * and used to query terrain. Probe objects exist both to capture which
+ * algorithm you have requested (see probe types) and also to cache query
+ * information.
+ * 
+ * Performance Guidelines
+ * ----------------------
+ * 
+ * It is generally faster to use the same probe for nearby points and
+ * different probes for different points. Try not to allocate more than
+ * "hundreds" of probes at most. Share probes if you need more. Generally,
+ * probing operations are expensive, and should be avoided via caching when
+ * possible.
+ * 
+ * Y testing returns a location on the terrain, a normal vector, and a
+ * velocity vector. The normal vector tells you the slope of the terrain at
+ * that point. The velocity vector tells you if that terrain is moving (and is
+ * in meters/second). For example, if your Y test hits the aircraft carrier
+ * deck, this tells you the velocity of that point on the deck.
+ * 
+ * Note: the Y-testing API is limited to probing the loaded scenery area,
+ * which is approximately 300x300 km in X-Plane 9. Probes outside this area
+ * will return the height of a 0 MSL sphere.
+ *
+ */
+
+
+/*
+ * XPLMProbeType
+ * 
+ * XPLMProbeType defines the type of terrain probe - each probe has a
+ * different algorithm. (Only one type of probe is provided right now, but
+ * future APIs will expose more flexible or powerful or useful probes.
+ *
+ */
+enum {
+    /* The Y probe gives you the location of the tallest physical scenery along   *
+     * the Y axis going through the queried point.                                */
+    xplm_ProbeY                              = 0,
+
+
+};
+typedef int XPLMProbeType;
+
+/*
+ * XPLMProbeResult
+ * 
+ * Probe results - possible results from a probe query.
+ *
+ */
+enum {
+    /* The probe hit terrain and returned valid values.                           */
+    xplm_ProbeHitTerrain                     = 0,
+
+    /* An error in the API call.  Either the probe struct size is bad, the probe  *
+     * is invalid, or the type is mismatched for the specific query call.         */
+    xplm_ProbeError                          = 1,
+
+    /* The probe call succeeded but there is no terrain under this point (perhaps *
+     * it is off the side of the planet?)                                         */
+    xplm_ProbeMissed                         = 2,
+
+
+};
+typedef int XPLMProbeResult;
+
+/*
+ * XPLMProbeRef
+ * 
+ * An XPLMProbeRef is an opaque handle to a probe, used for querying the
+ * terrain.
+ *
+ */
+typedef void * XPLMProbeRef;
+
+/*
+ * XPLMProbeInfo_t
+ * 
+ * XPLMProbeInfo_t contains the results of a probe call. Make sure to set
+ * structSize to the size of the struct before using it.
+ *
+ */
+typedef struct {
+    /* Size of structure in bytes - always set this before calling the XPLM.      */
+     int                       structSize;
+    /* Resulting X location of the terrain point we hit, in local OpenGL          *
+     * coordinates.                                                               */
+     float                     locationX;
+    /* Resulting Y location of the terrain point we hit, in local OpenGL          *
+     * coordinates.                                                               */
+     float                     locationY;
+    /* Resulting Z location of the terrain point we hit, in local OpenGL          *
+     * coordinates.                                                               */
+     float                     locationZ;
+    /* X component of the normal vector to the terrain we found.                  */
+     float                     normalX;
+    /* Y component of the normal vector to the terrain we found.                  */
+     float                     normalY;
+    /* Z component of the normal vector to the terrain we found.                  */
+     float                     normalZ;
+    /* X component of the velocity vector of the terrain we found.                */
+     float                     velocityX;
+    /* Y component of the velocity vector of the terrain we found.                */
+     float                     velocityY;
+    /* Z component of the velocity vector of the terrain we found.                */
+     float                     velocityZ;
+    /* Tells if the surface we hit is water (otherwise it is land).               */
+     int                       is_wet;
+} XPLMProbeInfo_t;
+
+/*
+ * XPLMCreateProbe
+ * 
+ * Creates a new probe object of a given type and returns.
+ *
+ */
+XPLM_API XPLMProbeRef XPLMCreateProbe(
+                         XPLMProbeType        inProbeType);
+
+/*
+ * XPLMDestroyProbe
+ * 
+ * Deallocates an existing probe object.
+ *
+ */
+XPLM_API void       XPLMDestroyProbe(
+                         XPLMProbeRef         inProbe);
+
+/*
+ * XPLMProbeTerrainXYZ
+ * 
+ * Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe
+ * object, and an XPLMProbeInfo_t struct that has its structSize member set
+ * properly. Other fields are filled in if we hit terrain, and a probe result
+ * is returned.
+ *
+ */
+XPLM_API XPLMProbeResult XPLMProbeTerrainXYZ(
+                         XPLMProbeRef         inProbe,
+                         float                inX,
+                         float                inY,
+                         float                inZ,
+                         XPLMProbeInfo_t *    outInfo);
+
+#endif /* XPLM200 */
+#if defined(XPLM300)
+/***************************************************************************
+ * Magnetic Variation
+ ***************************************************************************/
+/*
+ * Use the magnetic variation (more properly, the "magnetic declination") API
+ * to find the offset of magnetic north from true north at a given latitude
+ * and longitude within the simulator.
+ * 
+ * In the real world, the Earth's magnetic field is irregular, such that true
+ * north (the direction along a meridian toward the north pole) does not
+ * necessarily match what a magnetic compass shows as north.
+ * 
+ * Using this API ensures that you present the same offsets to users as
+ * X-Plane's built-in instruments.
+ *
+ */
+
+
+/*
+ * XPLMGetMagneticVariation
+ * 
+ * Returns X-Plane's simulated magnetic variation (declination) at the
+ * indication latitude and longitude.
+ *
+ */
+XPLM_API float      XPLMGetMagneticVariation(
+                         double               latitude,
+                         double               longitude);
+
+/*
+ * XPLMDegTrueToDegMagnetic
+ * 
+ * Converts a heading in degrees relative to true north into a value relative
+ * to magnetic north at the user's current location.
+ *
+ */
+XPLM_API float      XPLMDegTrueToDegMagnetic(
+                         float                headingDegreesTrue);
+
+/*
+ * XPLMDegMagneticToDegTrue
+ * 
+ * Converts a heading in degrees relative to magnetic north at the user's
+ * current location into a value relative to true north.
+ *
+ */
+XPLM_API float      XPLMDegMagneticToDegTrue(
+                         float                headingDegreesMagnetic);
+
+#endif /* XPLM300 */
+/***************************************************************************
+ * Object Drawing
+ ***************************************************************************/
+/*
+ * The object drawing routines let you load and draw X-Plane OBJ files.
+ * Objects are loaded by file path and managed via an opaque handle. X-Plane
+ * naturally reference counts objects, so it is important that you balance
+ * every successful call to XPLMLoadObject with a call to XPLMUnloadObject!
+ *
+ */
+
+
+#if defined(XPLM200)
+/*
+ * XPLMObjectRef
+ * 
+ * An XPLMObjectRef is a opaque handle to an .obj file that has been loaded
+ * into memory.
+ *
+ */
+typedef void * XPLMObjectRef;
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/*
+ * XPLMDrawInfo_t
+ * 
+ * The XPLMDrawInfo_t structure contains positioning info for one object that
+ * is to be drawn. Be sure to set structSize to the size of the structure for
+ * future expansion.
+ *
+ */
+typedef struct {
+    /* Set this to the size of this structure!                                    */
+     int                       structSize;
+    /* X location of the object in local coordinates.                             */
+     float                     x;
+    /* Y location of the object in local coordinates.                             */
+     float                     y;
+    /* Z location of the object in local coordinates.                             */
+     float                     z;
+    /* Pitch in degres to rotate the object, positive is up.                      */
+     float                     pitch;
+    /* Heading in local coordinates to rotate the object, clockwise.              */
+     float                     heading;
+    /* Roll to rotate the object.                                                 */
+     float                     roll;
+} XPLMDrawInfo_t;
+#endif /* XPLM200 */
+
+#if defined(XPLM210)
+/*
+ * XPLMObjectLoaded_f
+ * 
+ * You provide this callback when loading an object asynchronously; it will be
+ * called once the object is loaded. Your refcon is passed back. The object
+ * ref passed in is the newly loaded object (ready for use) or NULL if an
+ * error occured.
+ * 
+ * If your plugin is disabled, this callback will be delivered as soon as the
+ * plugin is re-enabled. If your plugin is unloaded before this callback is
+ * ever called, the SDK will release the object handle for you.
+ *
+ */
+typedef void (* XPLMObjectLoaded_f)(
+                         XPLMObjectRef        inObject,
+                         void *               inRefcon);
+#endif /* XPLM210 */
+
+#if defined(XPLM200)
+/*
+ * XPLMLoadObject
+ * 
+ * This routine loads an OBJ file and returns a handle to it. If X-Plane has
+ * already loaded the object, the handle to the existing object is returned.
+ * Do not assume you will get the same handle back twice, but do make sure to
+ * call unload once for every load to avoid "leaking" objects. The object will
+ * be purged from memory when no plugins and no scenery are using it.
+ * 
+ * The path for the object must be relative to the X-System base folder. If
+ * the path is in the root of the X-System folder you may need to prepend ./
+ * to it; loading objects in the root of the X-System folder is STRONGLY
+ * discouraged - your plugin should not dump art resources in the root folder!
+ * 
+ * XPLMLoadObject will return NULL if the object cannot be loaded (either
+ * because it is not found or the file is misformatted). This routine will
+ * load any object that can be used in the X-Plane scenery system.
+ * 
+ * It is important that the datarefs an object uses for animation already be
+ * registered before you load the object. For this reason it may be necessary
+ * to defer object loading until the sim has fully started.
+ *
+ */
+XPLM_API XPLMObjectRef XPLMLoadObject(
+                         const char *         inPath);
+#endif /* XPLM200 */
+
+#if defined(XPLM210)
+/*
+ * XPLMLoadObjectAsync
+ * 
+ * This routine loads an object asynchronously; control is returned to you
+ * immediately while X-Plane loads the object. The sim will not stop flying
+ * while the object loads. For large objects, it may be several seconds before
+ * the load finishes.
+ * 
+ * You provide a callback function that is called once the load has completed.
+ * Note that if the object cannot be loaded, you will not find out until the
+ * callback function is called with a NULL object handle.
+ * 
+ * There is no way to cancel an asynchronous object load; you must wait for
+ * the load to complete and then release the object if it is no longer
+ * desired.
+ *
+ */
+XPLM_API void       XPLMLoadObjectAsync(
+                         const char *         inPath,
+                         XPLMObjectLoaded_f   inCallback,
+                         void *               inRefcon);
+#endif /* XPLM210 */
+
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMDrawObjects
+ * 
+ * __Deprecation Warning__: use XPLMInstancing to draw 3-d objects by creating
+ * instances, rather than these APIs from draw callbacks.
+ * 
+ * XPLMDrawObjects draws an object from an OBJ file one or more times. You
+ * pass in the object and an array of XPLMDrawInfo_t structs, one for each
+ * place you would like the object to be drawn.
+ * 
+ * X-Plane will attempt to cull the objects based on LOD and visibility, and
+ * will pick the appropriate LOD.
+ * 
+ * Lighting is a boolean; pass 1 to show the night version of object with
+ * night-only lights lit up. Pass 0 to show the daytime version of the object.
+ * 
+ * earth_relative controls the coordinate system. If this is 1, the rotations
+ * you specify are applied to the object after its coordinate system is
+ * transformed from local to earth-relative coordinates -- that is, an object
+ * with no rotations will point toward true north and the Y axis will be up
+ * against gravity. If this is 0, the object is drawn with your rotations from
+ * local coordanates -- that is, an object with no rotations is drawn pointing
+ * down the -Z axis and the Y axis of the object matches the local coordinate
+ * Y axis.
+ *
+ */
+XPLM_API void       XPLMDrawObjects(
+                         XPLMObjectRef        inObject,
+                         int                  inCount,
+                         XPLMDrawInfo_t *     inLocations,
+                         int                  lighting,
+                         int                  earth_relative);
+#endif /* XPLM_DEPRECATED */
+
+#if defined(XPLM200)
+/*
+ * XPLMUnloadObject
+ * 
+ * This routine marks an object as no longer being used by your plugin.
+ * Objects are reference counted: once no plugins are using an object, it is
+ * purged from memory. Make sure to call XPLMUnloadObject once for each
+ * successful call to XPLMLoadObject.
+ *
+ */
+XPLM_API void       XPLMUnloadObject(
+                         XPLMObjectRef        inObject);
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/***************************************************************************
+ * Library Access
+ ***************************************************************************/
+/*
+ * The library access routines allow you to locate scenery objects via the
+ * X-Plane library system. Right now library access is only provided for
+ * objects, allowing plugin-drawn objects to be extended using the library
+ * system.
+ *
+ */
+
+
+/*
+ * XPLMLibraryEnumerator_f
+ * 
+ * An XPLMLibraryEnumerator_f is a callback you provide that is called once
+ * for each library element that is located. The returned paths will be
+ * relative to the X-System folder.
+ *
+ */
+typedef void (* XPLMLibraryEnumerator_f)(
+                         const char *         inFilePath,
+                         void *               inRef);
+
+/*
+ * XPLMLookupObjects
+ * 
+ * This routine looks up a virtual path in the library system and returns all
+ * matching elements. You provide a callback - one virtual path may match many
+ * objects in the library. XPLMLookupObjects returns the number of objects
+ * found.
+ * 
+ * The latitude and longitude parameters specify the location the object will
+ * be used. The library system allows for scenery packages to only provide
+ * objects to certain local locations. Only objects that are allowed at the
+ * latitude/longitude you provide will be returned.
+ *
+ */
+XPLM_API int        XPLMLookupObjects(
+                         const char *         inPath,
+                         float                inLatitude,
+                         float                inLongitude,
+                         XPLMLibraryEnumerator_f enumerator,
+                         void *               ref);
+
+#endif /* XPLM200 */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMSound.h b/SDK/CHeaders/XPLM/XPLMSound.h
new file mode 100644
index 0000000..9e89bb6
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMSound.h
@@ -0,0 +1,284 @@
+#ifndef _XPLMSound_h_
+#define _XPLMSound_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMSound
+ ***************************************************************************/
+/*
+ * This provides a minimal interface into the FMOD audio system. On the
+ * simplest level, you can request that X-Plane plays an in-memory audio
+ * buffer. This will work without linking to FMOD yourself. If you want to do
+ * anything more, such as modifying the sound, or loading banks and triggering
+ * your own events, you can get a pointer to the FMOD Studio instance.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(XPLM400)
+/***************************************************************************
+ * FMOD ACCESS
+ ***************************************************************************/
+
+/*
+ * XPLMAudioBus
+ * 
+ * This enumeration states the type of audio you wish to play - that is, the
+ * part of the simulated environment that the audio belongs in. If you use
+ * FMOD directly, note that COM1, COM2, Pilot and GND exist in a different
+ * FMOD bank so you may see these channels being unloaded/reloaded
+ * independently of the others. They may also be using a different
+ * FMOD::System if the user has selected a dedicated headset output device.
+ *
+ */
+enum {
+    /* Incoming speech on COM1                                                    */
+    xplm_AudioRadioCom1                      = 0,
+
+    /* Incoming speech on COM2                                                    */
+    xplm_AudioRadioCom2                      = 1,
+
+    /* Pilot's own speech                                                         */
+    xplm_AudioRadioPilot                     = 2,
+
+    /* Copilot's own speech                                                       */
+    xplm_AudioRadioCopilot                   = 3,
+
+    xplm_AudioExteriorAircraft               = 4,
+
+    xplm_AudioExteriorEnvironment            = 5,
+
+    xplm_AudioExteriorUnprocessed            = 6,
+
+    xplm_AudioInterior                       = 7,
+
+    xplm_AudioUI                             = 8,
+
+    /* Dedicated ground vehicle cable                                             */
+    xplm_AudioGround                         = 9,
+
+    /* Master bus. Not normally to be used directly.                              */
+    xplm_Master                              = 10,
+
+
+};
+typedef int XPLMAudioBus;
+
+/*
+ * XPLMBankID
+ * 
+ * These values are returned as the parameter of the
+ * "XPLM_MSG_FMOD_BANK_LOADED" and "XPLM_MSG_FMOD_BANK_UNLOADING" messages.
+ *
+ */
+enum {
+    /* Master bank. Handles all aircraft and environmental audio.                 */
+    xplm_MasterBank                          = 0,
+
+    /* Radio bank. Handles COM1/COM2/GND/Pilot/Copilot.                           */
+    xplm_RadioBank                           = 1,
+
+
+};
+typedef int XPLMBankID;
+
+
+/* 
+ * If you want to get full access to FMOD sound features, you need to include fmod.h or fmod.hpp yourself FIRST.
+ * If you only need the basic wrapper functions which allow 3D placement and playback on a specified channel, there
+ * is no need to link with full FMOD.
+ * It is recommended but not required that you don't mix methods - either use native FMOD calls or stick entirely
+ * within the functions of the X-Plane SDK.
+ *
+ * If you choose to use the advanced method, be aware that it is your responsibility to ensure that any resources,
+ * especially callbacks, are cleaned up when needed. The sound system may well be completely rebuild when the master 
+ * banks are reloaded, when aircraft are reloaded, or your plugin is unloaded.
+ *
+ * IMPORTANT: For all calls which use, or return, FMOD base types like FMOD_Studio_System*, these are fully interchangeable
+ *            with their C++ equivalents. See https://www.fmod.com/docs/2.02/api/white-papers-handle-system.html .
+ */
+#if defined(_FMOD_COMMON_H)
+
+/*
+ * XPLMGetFMODStudio
+ * 
+ * Get a handle to the FMOD Studio, allowing you to load/process whatever else
+ * you need. This also gives access to the underlying system via
+ * FMOD::Studio::System::getCoreSystem() / FMOD_Studio_System_GetCoreSystem()
+ * . When a separate output device is being used for the radio, this will
+ * always return the FMOD::Studio that is running the environment output, as
+ * before. If you want to specifically target the headset output device, you
+ * can obtain that FMOD::Studio by getting one of the radio-specific output
+ * channelgroups and using the getSystem() call on that.
+ *
+ */
+XPLM_API FMOD_STUDIO_SYSTEM* XPLMGetFMODStudio(void);
+
+/*
+ * XPLMGetFMODChannelGroup
+ * 
+ * Get a reference to a particular channel group - that is, an output channel.
+ * See the table above for values.
+ *
+ */
+XPLM_API FMOD_CHANNELGROUP* XPLMGetFMODChannelGroup(
+                         XPLMAudioBus         audioType);
+
+
+#else
+/*
+ * These definitions are enough to play a basic sound without linking to the full FMOD distribution. You can still position it in 3D
+ * and change other basic parameters. In all cases where an FMOD_RESULT is returned, the full range of FMOD_RESULT codes are used - the
+ * status will in almost all situations be coming straight from FMOD - so the single definition here is purely to create a matching
+ * datatype and allow simple "is OK" and "is not OK" tests.
+*/
+
+typedef enum FMOD_RESULT
+{
+    FMOD_OK,
+} FMOD_RESULT;
+typedef enum FMOD_SOUND_FORMAT
+{
+	FMOD_SOUND_FORMAT_PCM16 = 2
+} FMOD_SOUND_FORMAT;
+typedef struct FMOD_VECTOR
+{
+	float x, y, z;
+} FMOD_VECTOR;
+typedef void FMOD_CHANNEL;
+#endif
+
+/*
+ * XPLMPCMComplete_f
+ * 
+ * If you use XPLMPlayPCMOnBus() you may use this optional callback to find
+ * out when the FMOD::Channel is complete, if you need to deallocate memory
+ * for example.
+ *
+ */
+typedef void (* XPLMPCMComplete_f)(
+                         void *               inRefcon,
+                         FMOD_RESULT          status);
+
+/*
+ * XPLMPlayPCMOnBus
+ * 
+ * Play an in-memory audio buffer on a given audio bus. The resulting FMOD
+ * channel is returned. PAY ATTENTION TO THE CALLBACK - when the sample
+ * completes or is stopped by X-Plane, the channel will go away. It's up to
+ * you to listen for the callback and invalidate any copy of the channel
+ * pointer you have lying around. The callback is optional because if you have
+ * no intention of interacting with the sound after it's launched, then you
+ * don't need to keep the channel pointer at all. The sound is not started
+ * instantly. Instead, it will be started the next time X-Plane refreshes the
+ * sound system, typically at the start of the next frame. This allows you to
+ * set the initial position for the sound, if required. The callback will be
+ * called on the main thread, and will be called only once per sound. If the
+ * call fails and you provide a callback function, you will get a callback
+ * with an FMOD status code.
+ *
+ */
+XPLM_API FMOD_CHANNEL* XPLMPlayPCMOnBus(
+                         void *               audioBuffer,
+                         uint32_t             bufferSize,
+                         FMOD_SOUND_FORMAT    soundFormat,
+                         int                  freqHz,
+                         int                  numChannels,
+                         int                  loop,
+                         XPLMAudioBus         audioType,
+                         XPLMPCMComplete_f    inCallback,
+                         void *               inRefcon);              /* Can be NULL */
+
+/*
+ * XPLMStopAudio
+ * 
+ * Stop playing an active FMOD channel. If you defined a completion callback,
+ * this will be called. After this, the FMOD::Channel* will no longer be valid
+ * and must not be used in any future calls.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMStopAudio(
+                         FMOD_CHANNEL*        fmod_channel);
+
+/*
+ * XPLMSetAudioPosition
+ * 
+ * Move the given audio channel (i.e. a single sound) to a specific location
+ * in local co-ordinates. This will set the sound to 3D if it is not already.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMSetAudioPosition(
+                         FMOD_CHANNEL*        fmod_channel,
+                         FMOD_VECTOR*         position,
+                         FMOD_VECTOR*         velocity);
+
+/*
+ * XPLMSetAudioFadeDistance
+ * 
+ * Set the minimum and maximum fade distances for a given sound. This is
+ * highly unlikely to be 0 - please see
+ * https://documentation.help/FMOD-Studio-API/FMOD_Sound_Set3DMinMaxDistance.html
+ * for full details. This will set the sound to 3D if it is not already. You
+ * can set a 3D sound back to 2D by passing negative values for both min amd
+ * max.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMSetAudioFadeDistance(
+                         FMOD_CHANNEL*        fmod_channel,
+                         float                min_fade_distance,
+                         float                max_fade_distance);
+
+/*
+ * XPLMSetAudioVolume
+ * 
+ * Set the current volume of an active FMOD channel. This should be used to
+ * handle changes in the audio source volume, not for fading with distance.
+ * Values from 0 to 1 are normal, above 1 can be used to artificially amplify
+ * a sound.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMSetAudioVolume(
+                         FMOD_CHANNEL*        fmod_channel,
+                         float                source_volume);
+
+/*
+ * XPLMSetAudioPitch
+ * 
+ * Change the current pitch of an active FMOD channel.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMSetAudioPitch(
+                         FMOD_CHANNEL*        fmod_channel,
+                         float                audio_pitch_hz);
+
+/*
+ * XPLMSetAudioCone
+ * 
+ * Set a directional cone for an active FMOD channel. The orientation vector
+ * is in local coordinates. This will set the sound to 3D if it is not
+ * already.
+ *
+ */
+XPLM_API FMOD_RESULT XPLMSetAudioCone(
+                         FMOD_CHANNEL*        fmod_channel,
+                         float                inside_angle,
+                         float                outside_angle,
+                         float                outside_volume,
+                         FMOD_VECTOR*         orientation);
+
+#endif /* XPLM400 */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMUtilities.h b/SDK/CHeaders/XPLM/XPLMUtilities.h
new file mode 100644
index 0000000..d2fbf93
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMUtilities.h
@@ -0,0 +1,990 @@
+#ifndef _XPLMUtilities_h_
+#define _XPLMUtilities_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMUtilities
+ ***************************************************************************/
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * FILE UTILITIES
+ ***************************************************************************/
+/*
+ * The XPLMUtilities file APIs provide some basic file and path functions for
+ * use with X-Plane.
+ * 
+ * Directory Separators
+ * --------------------
+ * 
+ * The XPLM has two modes it can work in:
+ * 
+ *  * X-Plane native paths: all paths are UTF8 strings, using the unix forward
+ *    slash (/) as the directory separating character.  In native path mode,
+ *    you use the same path format for all three operating systems.
+ * 
+ *  * Legacy OS paths: the directroy separator is \ for Windows, : for OS X,
+ *    and / for Linux; OS paths are encoded in MacRoman for OS X using legacy
+ *    HFS conventions, use the application code page for multi-byte encoding
+ *    on Unix using DOS path conventions, and use UTF-8 for Linux.
+ * 
+ * While legacy OS paths are the default, we strongly encourage you to opt in
+ * to native paths using the XPLMEnableFeature API.
+ * 
+ *  * All OS X plugins should enable native paths all of the time; if you do
+ *    not do this, you will have to convert all paths back from HFS to Unix
+ *    (and deal with MacRoman) - code written using native paths and the C
+ *    file APIs "just works" on OS X.
+ * 
+ *  * For Linux plugins, there is no difference between the two encodings.
+ * 
+ *  * Windows plugins will need to convert the UTF8 file paths to UTF16 for
+ *    use with the "wide" APIs. While it might seem tempting to stick with
+ *    legacy OS paths (and just use the "ANSI" Windows APIs), X-Plane is fully
+ *    unicode-capable, and will often be installed in paths where the user's
+ *    directories have no ACP encoding.
+ * 
+ * Full and Relative Paths
+ * -----------------------
+ * 
+ * Some of these APIs use full paths, but others use paths relative to the
+ * user's X-Plane installation. This is documented on a per-API basis.
+ *
+ */
+
+
+#if defined(XPLM200)
+/*
+ * XPLMDataFileType
+ * 
+ * These enums define types of data files you can load or unload using the
+ * SDK.
+ *
+ */
+enum {
+    /* A situation (.sit) file, which starts off a flight in a given              *
+     * configuration.                                                             */
+    xplm_DataFile_Situation                  = 1,
+
+    /* A situation movie (.smo) file, which replays a past flight.                */
+    xplm_DataFile_ReplayMovie                = 2,
+
+
+};
+typedef int XPLMDataFileType;
+#endif /* XPLM200 */
+
+/*
+ * XPLMGetSystemPath
+ * 
+ * This function returns the full path to the X-System folder. Note that this
+ * is a directory path, so it ends in a trailing : or / .
+ * 
+ * The buffer you pass should be at least 512 characters long.  The path is
+ * returned using the current native or OS path conventions.
+ *
+ */
+XPLM_API void       XPLMGetSystemPath(
+                         char *               outSystemPath);
+
+/*
+ * XPLMGetPrefsPath
+ * 
+ * This routine returns a full path to a file that is within X-Plane's
+ * preferences directory. (You should remove the file name back to the last
+ * directory separator to get the preferences directory using
+ * XPLMExtractFileAndPath).
+ * 
+ * The buffer you pass should be at least 512 characters long.  The path is
+ * returned using the current native or OS path conventions.
+ *
+ */
+XPLM_API void       XPLMGetPrefsPath(
+                         char *               outPrefsPath);
+
+/*
+ * XPLMGetDirectorySeparator
+ * 
+ * This routine returns a string with one char and a null terminator that is
+ * the directory separator for the current platform. This allows you to write
+ * code that concatenates directory paths without having to #ifdef for
+ * platform. The character returned will reflect the current file path mode.
+ *
+ */
+XPLM_API const char * XPLMGetDirectorySeparator(void);
+
+/*
+ * XPLMExtractFileAndPath
+ * 
+ * Given a full path to a file, this routine separates the path from the file.
+ * If the path is a partial directory (e.g. ends in : or / ) the trailing
+ * directory separator is removed. This routine works in-place; a pointer to
+ * the file part of the buffer is returned; the original buffer still starts
+ * with the path and is null terminated with no trailing separator.
+ *
+ */
+XPLM_API char *     XPLMExtractFileAndPath(
+                         char *               inFullPath);
+
+/*
+ * XPLMGetDirectoryContents
+ * 
+ * This routine returns a list of files in a directory (specified by a full
+ * path, no trailing : or / ). The output is returned as a list of NULL
+ * terminated strings. An index array (if specified) is filled with pointers
+ * into the strings. The last file is indicated by a zero-length string (and
+ * NULL in the indices). This routine will return 1 if you had capacity for
+ * all files or 0 if you did not. You can also skip a given number of files.
+ * 
+ *  * inDirectoryPath - a null terminated C string containing the full path to
+ *    the directory with no trailing directory char.
+ * 
+ *  * inFirstReturn - the zero-based index of the first file in the directory
+ *    to return. (Usually zero to fetch all in one pass.)
+ * 
+ *  * outFileNames - a buffer to receive a series of sequential null
+ *    terminated C-string file names. A zero-length C string will be appended
+ *    to the very end.
+ * 
+ *  * inFileNameBufSize - the size of the file name buffer in bytes.
+ * 
+ *  * outIndices - a pointer to an array of character pointers that will
+ *    become an index into the directory. The last file will be followed by a
+ *    NULL value. Pass NULL if you do not want indexing information.
+ * 
+ *  * inIndexCount - the max size of the index in entries.
+ * 
+ *  * outTotalFiles - if not NULL, this is filled in with the number of files
+ *    in the directory.
+ * 
+ *  * outReturnedFiles - if not NULL, the number of files returned by this
+ *    iteration.
+ * 
+ * Return value: 1 if all info could be returned, 0 if there was a buffer
+ * overrun.
+ * 
+ * WARNING: Before X-Plane 7 this routine did not properly iterate through
+ * directories. If X-Plane
+ * 6 compatibility is needed, use your own code to iterate directories.
+ *
+ */
+XPLM_API int        XPLMGetDirectoryContents(
+                         const char *         inDirectoryPath,
+                         int                  inFirstReturn,
+                         char *               outFileNames,
+                         int                  inFileNameBufSize,
+                         char **              outIndices,             /* Can be NULL */
+                         int                  inIndexCount,
+                         int *                outTotalFiles,          /* Can be NULL */
+                         int *                outReturnedFiles);      /* Can be NULL */
+
+#if defined(XPLM200)
+/*
+ * XPLMLoadDataFile
+ * 
+ * Loads a data file of a given type. Paths must be relative to the X-System
+ * folder. To clear the replay, pass a NULL file name (this is only valid with
+ * replay movies, not sit files).
+ *
+ */
+XPLM_API int        XPLMLoadDataFile(
+                         XPLMDataFileType     inFileType,
+                         const char *         inFilePath);            /* Can be NULL */
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/*
+ * XPLMSaveDataFile
+ * 
+ * Saves the current situation or replay; paths are relative to the X-System
+ * folder.
+ *
+ */
+XPLM_API int        XPLMSaveDataFile(
+                         XPLMDataFileType     inFileType,
+                         const char *         inFilePath);
+#endif /* XPLM200 */
+
+/***************************************************************************
+ * X-PLANE MISC
+ ***************************************************************************/
+
+/*
+ * XPLMHostApplicationID
+ * 
+ * While the plug-in SDK is only accessible to plugins running inside X-Plane,
+ * the original authors considered extending the API to other applications
+ * that shared basic infrastructure with X-Plane. These enumerations are
+ * hold-overs from that original roadmap; all values other than X-Plane are
+ * deprecated. Your plugin should never need this enumeration.
+ *
+ */
+enum {
+    xplm_Host_Unknown                        = 0,
+
+    xplm_Host_XPlane                         = 1,
+
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_PlaneMaker                     = 2,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_WorldMaker                     = 3,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_Briefer                        = 4,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_PartMaker                      = 5,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_YoungsMod                      = 6,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_XAuto                          = 7,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_Xavion                         = 8,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_Control_Pad                    = 9,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_PFD_Map                        = 10,
+
+#endif /* XPLM_DEPRECATED */
+#if defined(XPLM_DEPRECATED)
+    xplm_Host_RADAR                          = 11,
+
+#endif /* XPLM_DEPRECATED */
+
+};
+typedef int XPLMHostApplicationID;
+
+/*
+ * XPLMLanguageCode
+ * 
+ * These enums define what language the sim is running in. These enumerations
+ * do not imply that the sim can or does run in all of these languages; they
+ * simply provide a known encoding in the event that a given sim version is
+ * localized to a certain language.
+ *
+ */
+enum {
+    xplm_Language_Unknown                    = 0,
+
+    xplm_Language_English                    = 1,
+
+    xplm_Language_French                     = 2,
+
+    xplm_Language_German                     = 3,
+
+    xplm_Language_Italian                    = 4,
+
+    xplm_Language_Spanish                    = 5,
+
+    xplm_Language_Korean                     = 6,
+
+#if defined(XPLM200)
+    xplm_Language_Russian                    = 7,
+
+#endif /* XPLM200 */
+#if defined(XPLM200)
+    xplm_Language_Greek                      = 8,
+
+#endif /* XPLM200 */
+#if defined(XPLM200)
+    xplm_Language_Japanese                   = 9,
+
+#endif /* XPLM200 */
+#if defined(XPLM300)
+    xplm_Language_Chinese                    = 10,
+
+#endif /* XPLM300 */
+#if defined(XPLM400)
+    xplm_Language_Ukrainian                  = 11,
+
+#endif /* XPLM400 */
+
+};
+typedef int XPLMLanguageCode;
+
+#if defined(XPLM200)
+/*
+ * XPLMError_f
+ * 
+ * An XPLM error callback is a function that you provide to receive debugging
+ * information from the plugin SDK. See XPLMSetErrorCallback for more
+ * information. NOTE: for the sake of debugging, your error callback will be
+ * called even if your plugin is not enabled, allowing you to receive debug
+ * info in your XPluginStart and XPluginStop callbacks. To avoid causing logic
+ * errors in the management code, do not call any other plugin routines from
+ * your error callback - it is only meant for catching errors in the
+ * debugging.
+ *
+ */
+typedef void (* XPLMError_f)(
+                         const char *         inMessage);
+#endif /* XPLM200 */
+
+#if defined(XPLM_DEPRECATED)
+/*
+ * XPLMInitialized
+ * 
+ * Deprecated: This function returns 1 if X-Plane has properly initialized the
+ * plug-in system. If this routine returns 0, many XPLM functions will not
+ * work.
+ * 
+ * NOTE: because plugins are always called from within the XPLM, there is no
+ * need to check for initialization; it will always return 1.  This routine is
+ * deprecated - you do not need to check it before continuing within your
+ * plugin.
+ *
+ */
+XPLM_API int        XPLMInitialized(void);
+#endif /* XPLM_DEPRECATED */
+
+/*
+ * XPLMGetVersions
+ * 
+ * This routine returns the revision of both X-Plane and the XPLM DLL. All
+ * versions are at least three-digit decimal numbers (e.g. 606 for version
+ * 6.06 of X-Plane); the current revision of the XPLM is 400 (4.00). This
+ * routine also returns the host ID of the app running us.
+ * 
+ * The most common use of this routine is to special-case around X-Plane
+ * version-specific behavior.
+ *
+ */
+XPLM_API void       XPLMGetVersions(
+                         int *                outXPlaneVersion,
+                         int *                outXPLMVersion,
+                         XPLMHostApplicationID * outHostID);
+
+/*
+ * XPLMGetLanguage
+ * 
+ * This routine returns the langauge the sim is running in.
+ *
+ */
+XPLM_API XPLMLanguageCode XPLMGetLanguage(void);
+
+#if defined(XPLM200)
+/*
+ * XPLMFindSymbol
+ * 
+ * This routine will attempt to find the symbol passed in the inString
+ * parameter. If the symbol is found a pointer the function is returned,
+ * othewise the function will return NULL.
+ * 
+ * You can use XPLMFindSymbol to utilize newer SDK API features without
+ * requiring newer versions of the SDK (and X-Plane) as your minimum X-Plane
+ * version as follows:
+ * 
+ *  * Define the XPLMnnn macro to the minimum required XPLM version you will
+ *    ship with (e.g. XPLM210 for X-Plane 10 compatibility).
+ * 
+ *  * Use XPLMGetVersions and XPLMFindSymbol to detect that the host sim is
+ *    new enough to use new functions and resolve function pointers.
+ * 
+ *  * Conditionally use the new functions if and only if XPLMFindSymbol only
+ *    returns a non- NULL pointer.
+ * 
+ * Warning: you should always check the XPLM API version as well as the
+ * results of XPLMFindSymbol to determine if funtionality is safe to use.
+ * 
+ * To use functionality via XPLMFindSymbol you will need to copy your own
+ * definitions of the X-Plane API prototypes and cast the returned pointer to
+ * the correct type.
+ *
+ */
+XPLM_API void *     XPLMFindSymbol(
+                         const char *         inString);
+#endif /* XPLM200 */
+
+#if defined(XPLM200)
+/*
+ * XPLMSetErrorCallback
+ * 
+ * XPLMSetErrorCallback installs an error-reporting callback for your plugin.
+ * Normally the plugin system performs minimum diagnostics to maximize
+ * performance. When you install an error callback, you will receive calls due
+ * to certain plugin errors, such as passing bad parameters or incorrect data.
+ * 
+ * Important: the error callback determines *programming* errors, e.g. bad API
+ * parameters. Every error that is returned by the error callback represents a
+ * mistake in your plugin that you should fix. Error callbacks are not used to
+ * report expected run-time problems (e.g. disk I/O errors).
+ * 
+ * The intention is for you to install the error callback during debug
+ * sections and put a break-point inside your callback. This will cause you to
+ * break into the debugger from within the SDK at the point in your plugin
+ * where you made an illegal call.
+ * 
+ * Installing an error callback may activate error checking code that would
+ * not normally run, and this may adversely affect performance, so do not
+ * leave error callbacks installed in shipping plugins. Since the only useful
+ * response to an error is to change code, error callbacks are not useful "in
+ * the field".
+ *
+ */
+XPLM_API void       XPLMSetErrorCallback(
+                         XPLMError_f          inCallback);
+#endif /* XPLM200 */
+
+/*
+ * XPLMDebugString
+ * 
+ * This routine outputs a C-style string to the Log.txt file. The file is
+ * immediately flushed so you will not lose data. (This does cause a
+ * performance penalty.)
+ * 
+ * Please do *not* leave routine diagnostic logging enabled in your shipping
+ * plugin. The X-Plane Log file is shared by X-Plane and every plugin in the
+ * system, and plugins that (when functioning normally) print verbose log
+ * output make it difficult for developers to find error conditions from other
+ * parts of the system.
+ *
+ */
+XPLM_API void       XPLMDebugString(
+                         const char *         inString);
+
+/*
+ * XPLMSpeakString
+ * 
+ * This function displays the string in a translucent overlay over the current
+ * display and also speaks the string if text-to-speech is enabled. The string
+ * is spoken asynchronously, this function returns immediately. This function
+ * may not speak or print depending on user preferences.
+ *
+ */
+XPLM_API void       XPLMSpeakString(
+                         const char *         inString);
+
+/*
+ * XPLMGetVirtualKeyDescription
+ * 
+ * Given a virtual key code (as defined in XPLMDefs.h) this routine returns a
+ * human-readable string describing the character. This routine is provided
+ * for showing users what keyboard mappings they have set up. The string may
+ * read 'unknown' or be a blank or NULL string if the virtual key is unknown.
+ *
+ */
+XPLM_API const char * XPLMGetVirtualKeyDescription(
+                         char                 inVirtualKey);
+
+/*
+ * XPLMReloadScenery
+ * 
+ * XPLMReloadScenery reloads the current set of scenery. You can use this
+ * function in two typical ways: simply call it to reload the scenery, picking
+ * up any new installed scenery, .env files, etc. from disk. Or, change the
+ * lat/ref and lon/ref datarefs and then call this function to shift the
+ * scenery environment.  This routine is equivalent to picking "reload
+ * scenery" from the developer menu.
+ *
+ */
+XPLM_API void       XPLMReloadScenery(void);
+
+#if defined(XPLM200)
+/***************************************************************************
+ * X-PLANE COMMAND MANAGEMENT
+ ***************************************************************************/
+/*
+ * The command management APIs let plugins interact with the command-system in
+ * X-Plane, the abstraction behind keyboard presses and joystick buttons. This
+ * API lets you create new commands and modify the behavior (or get
+ * notification) of existing ones.
+ * 
+ * X-Plane Command Phases
+ * ----------------------
+ * 
+ * X-Plane commands are not instantaneous; they operate over a duration.
+ * (Think of a joystick button press - you can press, hold down, and then
+ * release the joystick button; X-Plane commands model this entire process.)
+ * 
+ * An X-Plane command consists of three phases: a beginning, continuous
+ * repetition, and an ending. The command may be repeated zero times in its
+ * duration, followed by one command ending. Command begin and end messges are
+ * balanced, but a command may be bound to more than one event source (e.g. a
+ * keyboard key and a joystick button), in which case you may receive a second
+ * begin during before any end).
+ * 
+ * When you issue commands in the plugin system, you *must* balance every call
+ * to XPLMCommandBegin with a call to XPLMCommandEnd with the same command
+ * reference.
+ * 
+ * Command Behavior Modification
+ * -----------------------------
+ * 
+ * You can register a callback to handle a command either before or after
+ * X-Plane does; if you receive the command before X-Plane you have the option
+ * to either let X-Plane handle the command or hide the command from X-Plane.
+ * This lets plugins both augment commands and replace them.
+ * 
+ * If you register for an existing command, be sure that you are *consistent*
+ * in letting X-Plane handle or not handle the command; you are responsible
+ * for passing a *balanced* number of begin and end messages to X-Plane. (E.g.
+ * it is not legal to pass all the begin messages to X-Plane but hide all the
+ * end messages).
+ *
+ */
+
+
+/*
+ * XPLMCommandPhase
+ * 
+ * The phases of a command.
+ *
+ */
+enum {
+    /* The command is being started.                                              */
+    xplm_CommandBegin                        = 0,
+
+    /* The command is continuing to execute.                                      */
+    xplm_CommandContinue                     = 1,
+
+    /* The command has ended.                                                     */
+    xplm_CommandEnd                          = 2,
+
+
+};
+typedef int XPLMCommandPhase;
+
+/*
+ * XPLMCommandRef
+ * 
+ * A command ref is an opaque identifier for an X-Plane command. Command
+ * references stay the same for the life of your plugin but not between
+ * executions of X-Plane. Command refs are used to execute commands, create
+ * commands, and create callbacks for particular commands.
+ * 
+ * Note that a command is not "owned" by a particular plugin. Since many
+ * plugins may participate in a command's execution, the command does not go
+ * away if the plugin that created it is unloaded.
+ *
+ */
+typedef void * XPLMCommandRef;
+
+/*
+ * XPLMCommandCallback_f
+ * 
+ * A command callback is a function in your plugin that is called when a
+ * command is pressed. Your callback receives the command reference for the
+ * particular command, the phase of the command that is executing, and a
+ * reference pointer that you specify when registering the callback.
+ * 
+ * Your command handler should return 1 to let processing of the command
+ * continue to other plugins and X-Plane, or 0 to halt processing, potentially
+ * bypassing X-Plane code.
+ *
+ */
+typedef int (* XPLMCommandCallback_f)(
+                         XPLMCommandRef       inCommand,
+                         XPLMCommandPhase     inPhase,
+                         void *               inRefcon);
+
+/*
+ * XPLMFindCommand
+ * 
+ * XPLMFindCommand looks up a command by name, and returns its command
+ * reference or NULL if the command does not exist.
+ *
+ */
+XPLM_API XPLMCommandRef XPLMFindCommand(
+                         const char *         inName);
+
+/*
+ * XPLMCommandBegin
+ * 
+ * XPLMCommandBegin starts the execution of a command, specified by its
+ * command reference. The command is "held down" until XPLMCommandEnd is
+ * called.  You must balance each XPLMCommandBegin call with an XPLMCommandEnd
+ * call.
+ *
+ */
+XPLM_API void       XPLMCommandBegin(
+                         XPLMCommandRef       inCommand);
+
+/*
+ * XPLMCommandEnd
+ * 
+ * XPLMCommandEnd ends the execution of a given command that was started with
+ * XPLMCommandBegin.  You must not issue XPLMCommandEnd for a command you did
+ * not begin.
+ *
+ */
+XPLM_API void       XPLMCommandEnd(
+                         XPLMCommandRef       inCommand);
+
+/*
+ * XPLMCommandOnce
+ * 
+ * This executes a given command momentarily, that is, the command begins and
+ * ends immediately. This is the equivalent of calling XPLMCommandBegin() and
+ * XPLMCommandEnd() back to back.
+ *
+ */
+XPLM_API void       XPLMCommandOnce(
+                         XPLMCommandRef       inCommand);
+
+/*
+ * XPLMCreateCommand
+ * 
+ * XPLMCreateCommand creates a new command for a given string. If the command
+ * already exists, the existing command reference is returned. The description
+ * may appear in user interface contexts, such as the joystick configuration
+ * screen.
+ *
+ */
+XPLM_API XPLMCommandRef XPLMCreateCommand(
+                         const char *         inName,
+                         const char *         inDescription);
+
+/*
+ * XPLMRegisterCommandHandler
+ * 
+ * XPLMRegisterCommandHandler registers a callback to be called when a command
+ * is executed. You provide a callback with a reference pointer.
+ * 
+ * If inBefore is true, your command handler callback will be executed before
+ * X-Plane executes the command, and returning 0 from your callback will
+ * disable X-Plane's processing of the command. If inBefore is false, your
+ * callback will run after X-Plane. (You can register a single callback both
+ * before and after a command.)
+ *
+ */
+XPLM_API void       XPLMRegisterCommandHandler(
+                         XPLMCommandRef       inComand,
+                         XPLMCommandCallback_f inHandler,
+                         int                  inBefore,
+                         void *               inRefcon);
+
+/*
+ * XPLMUnregisterCommandHandler
+ * 
+ * XPLMUnregisterCommandHandler removes a command callback registered with
+ * XPLMRegisterCommandHandler.
+ *
+ */
+XPLM_API void       XPLMUnregisterCommandHandler(
+                         XPLMCommandRef       inComand,
+                         XPLMCommandCallback_f inHandler,
+                         int                  inBefore,
+                         void *               inRefcon);
+
+#endif /* XPLM200 */
+#if defined(XPLM_DEPRECATED)
+/***************************************************************************
+ * X-PLANE USER INTERACTION
+ ***************************************************************************/
+/*
+ * WARNING: The legacy user interaction API is deprecated; while it was the
+ * only way to run commands in X-Plane 6,7 and 8, it is obsolete, and was
+ * replaced by the command system API in X-Plane 9. You should not use this
+ * API; replace any of the calls below with XPLMCommand invocations based on
+ * persistent command strings. The documentation that follows is for historic
+ * reference only.
+ * 
+ * The legacy user interaction APIs let you simulate commands the user can do
+ * with a joystick, keyboard etc. Note that it is generally safer for future
+ * compatibility to use one of these commands than to manipulate the
+ * underlying sim data.
+ *
+ */
+
+
+/*
+ * XPLMCommandKeyID
+ * 
+ * These enums represent all the keystrokes available within X-Plane. They can
+ * be sent to X-Plane directly. For example, you can reverse thrust using
+ * these enumerations.
+ *
+ */
+enum {
+          xplm_key_pause=0,
+          xplm_key_revthrust,
+          xplm_key_jettison,
+          xplm_key_brakesreg,
+          xplm_key_brakesmax,
+          xplm_key_gear,
+          xplm_key_timedn,
+          xplm_key_timeup,
+          xplm_key_fadec,
+          xplm_key_otto_dis,
+          xplm_key_otto_atr,
+          xplm_key_otto_asi,
+          xplm_key_otto_hdg,
+          xplm_key_otto_gps,
+          xplm_key_otto_lev,
+          xplm_key_otto_hnav,
+          xplm_key_otto_alt,
+          xplm_key_otto_vvi,
+          xplm_key_otto_vnav,
+          xplm_key_otto_nav1,
+          xplm_key_otto_nav2,
+          xplm_key_targ_dn,
+          xplm_key_targ_up,
+          xplm_key_hdgdn,
+          xplm_key_hdgup,
+          xplm_key_barodn,
+          xplm_key_baroup,
+          xplm_key_obs1dn,
+          xplm_key_obs1up,
+          xplm_key_obs2dn,
+          xplm_key_obs2up,
+          xplm_key_com1_1,
+          xplm_key_com1_2,
+          xplm_key_com1_3,
+          xplm_key_com1_4,
+          xplm_key_nav1_1,
+          xplm_key_nav1_2,
+          xplm_key_nav1_3,
+          xplm_key_nav1_4,
+          xplm_key_com2_1,
+          xplm_key_com2_2,
+          xplm_key_com2_3,
+          xplm_key_com2_4,
+          xplm_key_nav2_1,
+          xplm_key_nav2_2,
+          xplm_key_nav2_3,
+          xplm_key_nav2_4,
+          xplm_key_adf_1,
+          xplm_key_adf_2,
+          xplm_key_adf_3,
+          xplm_key_adf_4,
+          xplm_key_adf_5,
+          xplm_key_adf_6,
+          xplm_key_transpon_1,
+          xplm_key_transpon_2,
+          xplm_key_transpon_3,
+          xplm_key_transpon_4,
+          xplm_key_transpon_5,
+          xplm_key_transpon_6,
+          xplm_key_transpon_7,
+          xplm_key_transpon_8,
+          xplm_key_flapsup,
+          xplm_key_flapsdn,
+          xplm_key_cheatoff,
+          xplm_key_cheaton,
+          xplm_key_sbrkoff,
+          xplm_key_sbrkon,
+          xplm_key_ailtrimL,
+          xplm_key_ailtrimR,
+          xplm_key_rudtrimL,
+          xplm_key_rudtrimR,
+          xplm_key_elvtrimD,
+          xplm_key_elvtrimU,
+          xplm_key_forward,
+          xplm_key_down,
+          xplm_key_left,
+          xplm_key_right,
+          xplm_key_back,
+          xplm_key_tower,
+          xplm_key_runway,
+          xplm_key_chase,
+          xplm_key_free1,
+          xplm_key_free2,
+          xplm_key_spot,
+          xplm_key_fullscrn1,
+          xplm_key_fullscrn2,
+          xplm_key_tanspan,
+          xplm_key_smoke,
+          xplm_key_map,
+          xplm_key_zoomin,
+          xplm_key_zoomout,
+          xplm_key_cycledump,
+          xplm_key_replay,
+          xplm_key_tranID,
+          xplm_key_max
+};
+typedef int XPLMCommandKeyID;
+
+/*
+ * XPLMCommandButtonID
+ * 
+ * These are enumerations for all of the things you can do with a joystick
+ * button in X-Plane. They currently match the buttons menu in the equipment
+ * setup dialog, but these enums will be stable even if they change in
+ * X-Plane.
+ *
+ */
+enum {
+          xplm_joy_nothing=0,
+          xplm_joy_start_all,
+          xplm_joy_start_0,
+          xplm_joy_start_1,
+          xplm_joy_start_2,
+          xplm_joy_start_3,
+          xplm_joy_start_4,
+          xplm_joy_start_5,
+          xplm_joy_start_6,
+          xplm_joy_start_7,
+          xplm_joy_throt_up,
+          xplm_joy_throt_dn,
+          xplm_joy_prop_up,
+          xplm_joy_prop_dn,
+          xplm_joy_mixt_up,
+          xplm_joy_mixt_dn,
+          xplm_joy_carb_tog,
+          xplm_joy_carb_on,
+          xplm_joy_carb_off,
+          xplm_joy_trev,
+          xplm_joy_trm_up,
+          xplm_joy_trm_dn,
+          xplm_joy_rot_trm_up,
+          xplm_joy_rot_trm_dn,
+          xplm_joy_rud_lft,
+          xplm_joy_rud_cntr,
+          xplm_joy_rud_rgt,
+          xplm_joy_ail_lft,
+          xplm_joy_ail_cntr,
+          xplm_joy_ail_rgt,
+          xplm_joy_B_rud_lft,
+          xplm_joy_B_rud_rgt,
+          xplm_joy_look_up,
+          xplm_joy_look_dn,
+          xplm_joy_look_lft,
+          xplm_joy_look_rgt,
+          xplm_joy_glance_l,
+          xplm_joy_glance_r,
+          xplm_joy_v_fnh,
+          xplm_joy_v_fwh,
+          xplm_joy_v_tra,
+          xplm_joy_v_twr,
+          xplm_joy_v_run,
+          xplm_joy_v_cha,
+          xplm_joy_v_fr1,
+          xplm_joy_v_fr2,
+          xplm_joy_v_spo,
+          xplm_joy_flapsup,
+          xplm_joy_flapsdn,
+          xplm_joy_vctswpfwd,
+          xplm_joy_vctswpaft,
+          xplm_joy_gear_tog,
+          xplm_joy_gear_up,
+          xplm_joy_gear_down,
+          xplm_joy_lft_brake,
+          xplm_joy_rgt_brake,
+          xplm_joy_brakesREG,
+          xplm_joy_brakesMAX,
+          xplm_joy_speedbrake,
+          xplm_joy_ott_dis,
+          xplm_joy_ott_atr,
+          xplm_joy_ott_asi,
+          xplm_joy_ott_hdg,
+          xplm_joy_ott_alt,
+          xplm_joy_ott_vvi,
+          xplm_joy_tim_start,
+          xplm_joy_tim_reset,
+          xplm_joy_ecam_up,
+          xplm_joy_ecam_dn,
+          xplm_joy_fadec,
+          xplm_joy_yaw_damp,
+          xplm_joy_art_stab,
+          xplm_joy_chute,
+          xplm_joy_JATO,
+          xplm_joy_arrest,
+          xplm_joy_jettison,
+          xplm_joy_fuel_dump,
+          xplm_joy_puffsmoke,
+          xplm_joy_prerotate,
+          xplm_joy_UL_prerot,
+          xplm_joy_UL_collec,
+          xplm_joy_TOGA,
+          xplm_joy_shutdown,
+          xplm_joy_con_atc,
+          xplm_joy_fail_now,
+          xplm_joy_pause,
+          xplm_joy_rock_up,
+          xplm_joy_rock_dn,
+          xplm_joy_rock_lft,
+          xplm_joy_rock_rgt,
+          xplm_joy_rock_for,
+          xplm_joy_rock_aft,
+          xplm_joy_idle_hilo,
+          xplm_joy_lanlights,
+          xplm_joy_max
+};
+typedef int XPLMCommandButtonID;
+
+/*
+ * XPLMSimulateKeyPress
+ * 
+ * This function simulates a key being pressed for X-Plane. The keystroke goes
+ * directly to X-Plane; it is never sent to any plug-ins. However, since this
+ * is a raw key stroke it may be mapped by the keys file or enter text into a
+ * field.
+ * 
+ * Deprecated: use XPLMCommandOnce
+ *
+ */
+XPLM_API void       XPLMSimulateKeyPress(
+                         int                  inKeyType,
+                         int                  inKey);
+
+/*
+ * XPLMCommandKeyStroke
+ * 
+ * This routine simulates a command-key stroke. However, the keys are done by
+ * function, not by actual letter, so this function works even if the user has
+ * remapped their keyboard. Examples of things you might do with this include
+ * pausing the simulator.
+ * 
+ * Deprecated: use XPLMCommandOnce
+ *
+ */
+XPLM_API void       XPLMCommandKeyStroke(
+                         XPLMCommandKeyID     inKey);
+
+/*
+ * XPLMCommandButtonPress
+ * 
+ * This function simulates any of the actions that might be taken by pressing
+ * a joystick button. However, this lets you call the command directly rather
+ * than having to know which button is mapped where. Important: you must
+ * release each button you press. The APIs are separate so that you can 'hold
+ * down' a button for a fixed amount of time.
+ * 
+ * Deprecated: use XPLMCommandBegin.
+ *
+ */
+XPLM_API void       XPLMCommandButtonPress(
+                         XPLMCommandButtonID  inButton);
+
+/*
+ * XPLMCommandButtonRelease
+ * 
+ * This function simulates any of the actions that might be taken by pressing
+ * a joystick button. See XPLMCommandButtonPress.
+ * 
+ * Deprecated: use XPLMCommandEnd.
+ *
+ */
+XPLM_API void       XPLMCommandButtonRelease(
+                         XPLMCommandButtonID  inButton);
+
+#endif /* XPLM_DEPRECATED */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/CHeaders/XPLM/XPLMWeather.h b/SDK/CHeaders/XPLM/XPLMWeather.h
new file mode 100644
index 0000000..3f1f50f
--- /dev/null
+++ b/SDK/CHeaders/XPLM/XPLMWeather.h
@@ -0,0 +1,146 @@
+#ifndef _XPLMWeather_h_
+#define _XPLMWeather_h_
+
+/*
+ * Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+ * rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+ *
+ */
+
+/***************************************************************************
+ * XPLMWeather
+ ***************************************************************************/
+/*
+ * This provides access to the X-Plane 12 enhanced weather system.
+ *
+ */
+
+#include "XPLMDefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************
+ * WEATHER ACCESS
+ ***************************************************************************/
+
+/*
+ * XPLMWeatherInfoWinds_t
+ *
+ */
+typedef struct {
+    /* Altitude MSL, meters                                                       */
+     float                     alt_msl;
+    /* Wind speed, meters/sec                                                     */
+     float                     speed;
+    /* Direction (true)                                                           */
+     float                     direction;
+    /* Gust speed, meters/sec                                                     */
+     float                     gust_speed;
+    /* Shear arc, degrees i.e. 50% of this arc in either direction from base      */
+     float                     shear;
+    /* Clear-air turbulence ratio                                                 */
+     float                     turbulence;
+} XPLMWeatherInfoWinds_t;
+
+/*
+ * XPLMWeatherInfoClouds_t
+ *
+ */
+typedef struct {
+    /* Cloud type, float enum                                                     */
+     float                     cloud_type;
+    /* Coverage ratio                                                             */
+     float                     coverage;
+    /* Altitude MSL, meters                                                       */
+     float                     alt_top;
+    /* Altitude MSL, meters                                                       */
+     float                     alt_base;
+} XPLMWeatherInfoClouds_t;
+
+/*
+ * XPLMWeatherInfo_t
+ * 
+ * Basic weather conditions at a specific point.
+ *
+ */
+typedef struct {
+    /* The size of the struct.                                                    */
+     int                       structSize;
+    /* Temperature at the given altitude in Celsius                               */
+     float                     temperature_alt;
+    /* Dewpoint at the given altitude in Celsius                                  */
+     float                     dewpoint_alt;
+    /* Pressure at the given altitude in Pascals                                  */
+     float                     pressure_alt;
+    /* Precipitation rate at the given altitude                                   */
+     float                     precip_rate_alt;
+    /* Wind direction at the given altitude                                       */
+     float                     wind_dir_alt;
+    /* Wind speed at the given altitude, meters/sec                               */
+     float                     wind_spd_alt;
+    /* Turbulence ratio at the given altitude                                     */
+     float                     turbulence_alt;
+    /* Height of water waves in meters                                            */
+     float                     wave_height;
+    /* Length of water waves in meters                                            */
+     float                     wave_length;
+    /* Direction from which water waves are coming                                */
+     int                       wave_dir;
+    /* Speed of wave advance in meters/sec                                        */
+     float                     wave_speed;
+    /* Base visibility at 0 altitude, meters                                      */
+     float                     visibility;
+    /* Base precipitation ratio at 0 altitude                                     */
+     float                     precip_rate;
+    /* Climb rate due to thermals, meters/sec                                     */
+     float                     thermal_climb;
+    /* Pressure at 0 altitude in Pascals                                          */
+     float                     pressure_sl;
+    /* Defined wind layers. Not all layers are always defined.                    */
+     XPLMWeatherInfoWinds_t    wind_layers[13];
+    /* Defined cloud layers. Not all layers are always defined.                   */
+     XPLMWeatherInfoClouds_t   cloud_layers[3];
+} XPLMWeatherInfo_t;
+
+#if defined(XPLM400)
+/*
+ * XPLMGetMETARForAirport
+ * 
+ * Get the last-downloaded METAR report for an airport by ICAO code. Note that
+ * the actual weather at that airport may have evolved significantly since the
+ * last downloaded METAR. outMETAR must point to a char buffer of at least 150
+ * characters. This call is not intended to be used per-frame. This call does
+ * not return the current weather at the airport, and returns an empty string
+ * if the system is not in real-weather mode.
+ *
+ */
+XPLM_API void       XPLMGetMETARForAirport(
+                         const char *         airport_id,
+                         XPLMFixedString150_t * outMETAR);
+#endif /* XPLM400 */
+
+#if defined(XPLM400)
+/*
+ * XPLMGetWeatherAtLocation
+ * 
+ * Get the current weather conditions at a given location. Note that this does
+ * not work world-wide, only within the surrounding region. Return 1 if
+ * detailed weather (i.e. an airport-specific METAR) was found, 0 if not. In
+ * both cases, the structure will contain the best data available. This call
+ * is not intended to be used per-frame.
+ *
+ */
+XPLM_API int        XPLMGetWeatherAtLocation(
+                         double               latitude,
+                         double               longitude,
+                         double               altitude_m,
+                         XPLMWeatherInfo_t *  out_info);
+#endif /* XPLM400 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/SDK/Delphi/Widgets/XPStandardWidgets.pas b/SDK/Delphi/Widgets/XPStandardWidgets.pas
new file mode 100644
index 0000000..2bb5f8c
--- /dev/null
+++ b/SDK/Delphi/Widgets/XPStandardWidgets.pas
@@ -0,0 +1,470 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPStandardWidgets;
+INTERFACE
+{
+   ## THEORY OF OPERATION
+   
+   The standard widgets are widgets built into the widgets library. While you
+   can gain access to the widget function that drives them, you generally use
+   them by calling XPCreateWidget and then listening for special messages,
+   etc.
+   
+   The standard widgets often send messages to themselves when the user
+   performs an event; these messages are sent up the widget hierarchy until
+   they are handled. So you can add a widget proc directly to a push button
+   (for example) to intercept the message when it is clicked, or you can put
+   one widget proc on a window for all of the push buttons in the window. Most
+   of these messages contain the original widget ID as a parameter so you can
+   know which widget is messaging no matter who it is sent to.
+}
+
+USES
+    XPWidgetDefs;
+   {$A4}
+{___________________________________________________________________________
+ * MAIN WINDOW
+ ___________________________________________________________________________}
+{
+   The main window widget class provides a "window" as the user knows it.
+   These windows are draggable and can be selected. Use them to create
+   floating windows and non-modal dialogs.
+}
+
+
+CONST
+   xpWidgetClass_MainWindow = 1;
+
+   {
+    Main Window Type Values
+    
+    These type values are used to control the appearance of a main window.
+   }
+     { The standard main window; pin stripes on XP7, metal frame on XP 6.         }
+      xpMainWindowStyle_MainWindow             = 0
+;
+     { A translucent dark gray window.                                            }
+      xpMainWindowStyle_Translucent            = 1
+;
+
+   {
+    Main Window Properties
+   }
+     { This property specifies the type of window.  Set to one of the main window }
+     { types above.                                                               }
+      xpProperty_MainWindowType                = 1100
+;
+     { This property specifies whether the main window has close boxes in its     }
+     { corners.                                                                   }
+      xpProperty_MainWindowHasCloseBoxes       = 1200
+;
+
+   {
+    MainWindow Messages
+   }
+     { This message is sent when the close buttons for your window are pressed.   }
+      xpMessage_CloseButtonPushed              = 1200
+;
+
+{___________________________________________________________________________
+ * SUB WINDOW
+ ___________________________________________________________________________}
+{
+   X-Plane dialogs are divided into separate areas; the sub window widgets
+   allow you to make these areas. Create one main window and place several
+   subwindows inside it. Then place your controls inside the subwindows.
+}
+
+
+CONST
+   xpWidgetClass_SubWindow = 2;
+
+   {
+    SubWindow Type Values
+    
+    These values control the appearance of the subwindow.
+   }
+     { A panel that sits inside a main window.                                    }
+      xpSubWindowStyle_SubWindow               = 0
+;
+     { A screen that sits inside a panel for showing text information.            }
+      xpSubWindowStyle_Screen                  = 2
+;
+     { A list view for scrolling lists.                                           }
+      xpSubWindowStyle_ListView                = 3
+;
+
+   {
+    SubWindow Properties
+   }
+     { This property specifies the type of window.  Set to one of the subwindow   }
+     { types above.                                                               }
+      xpProperty_SubWindowType                 = 1200
+;
+
+{___________________________________________________________________________
+ * BUTTON
+ ___________________________________________________________________________}
+{
+   The button class provides a number of different button styles and
+   behaviors, including push buttons, radio buttons, check boxes, etc. The
+   button label appears on or next to the button depending on the button's
+   appearance or type.
+   
+   The button's behavior is a separate property that dictates who it
+   highlights and what kinds of messages it sends. Since behavior and type are
+   different, you can do strange things like make check boxes that act as push
+   buttons or push buttons with radio button behavior.
+   
+   In X-Plane 6 there were no check box graphics. The result is the following
+   behavior: in X-Plane
+   6 all check box and radio buttons are round (radio-button style) buttons;
+     in X-Plane 7 they are all square (check-box style) buttons. In a future
+     version of X-Plane, the xpButtonBehavior enums will provide the correct
+     graphic (check box or radio button) giving the expected result.
+}
+
+
+CONST
+   xpWidgetClass_Button = 3;
+
+   {
+    Button Types
+    
+    These define the visual appearance of buttons but not how they respond to
+    the mouse.
+   }
+     { This is a standard push button, like an 'OK' or 'Cancel' button in a dialog}
+     { box.                                                                       }
+      xpPushButton                             = 0
+;
+     { A check box or radio button.  Use this and the button behaviors below to   }
+     { get the desired behavior.                                                  }
+      xpRadioButton                            = 1
+;
+     { A window close box.                                                        }
+      xpWindowCloseBox                         = 3
+;
+     { A small down arrow.                                                        }
+      xpLittleDownArrow                        = 5
+;
+     { A small up arrow.                                                          }
+      xpLittleUpArrow                          = 6
+;
+
+   {
+    Button Behavior Values
+    
+    These define how the button responds to mouse clicks.
+   }
+     { Standard push button behavior. The button highlights while the mouse is    }
+     { clicked over it and unhighlights when the mouse is moved outside of it or  }
+     { released. If the mouse is released over the button, the                    }
+     { xpMsg_PushButtonPressed message is sent.                                   }
+      xpButtonBehaviorPushButton               = 0
+;
+     { Check box behavior. The button immediately toggles its value when the mouse}
+     { is clicked and sends out a xpMsg_ButtonStateChanged message.               }
+      xpButtonBehaviorCheckBox                 = 1
+;
+     { Radio button behavior. The button immediately sets its state to one and    }
+     { sends out a xpMsg_ButtonStateChanged message if it was not already set to  }
+     { one. You must turn off other radio buttons in a group in your code.        }
+      xpButtonBehaviorRadioButton              = 2
+;
+
+   {
+    Button Properties
+   }
+     { This property sets the visual type of button.  Use one of the button types }
+     { above.                                                                     }
+      xpProperty_ButtonType                    = 1300
+;
+     { This property sets the button's behavior.  Use one of the button behaviors }
+     { above.                                                                     }
+      xpProperty_ButtonBehavior                = 1301
+;
+     { This property tells whether a check box or radio button is "checked" or    }
+     { not. Not used for push buttons.                                            }
+      xpProperty_ButtonState                   = 1302
+;
+
+   {
+    Button Messages
+    
+    These messages are sent by the button to itself and then up the widget
+    chain when the button is clicked. (You may intercept them by providing a
+    widget handler for the button itself or by providing a handler in a parent
+    widget.)
+   }
+     { This message is sent when the user completes a click and release in a      }
+     { button with push button behavior. Parameter one of the message is the      }
+     { widget ID of the button. This message is dispatched up the widget          }
+     { hierarchy.                                                                 }
+      xpMsg_PushButtonPressed                  = 1300
+;
+     { This message is sent when a button is clicked that has radio button or     }
+     { check box behavior and its value changes. (Note that if the value changes  }
+     { by setting a property you do not receive this message!) Parameter one is   }
+     { the widget ID of the button, parameter 2 is the new state value, either    }
+     { zero or one. This message is dispatched up the widget hierarchy.           }
+      xpMsg_ButtonStateChanged                 = 1301
+;
+
+{___________________________________________________________________________
+ * TEXT FIELD
+ ___________________________________________________________________________}
+{
+   The text field widget provides an editable text field including mouse
+   selection and keyboard navigation. The contents of the text field are its
+   descriptor. (The descriptor changes as the user types.)
+   
+   The text field can have a number of types, that affect the visual layout of
+   the text field. The text field sends messages to itself so you may control
+   its behavior.
+   
+   If you need to filter keystrokes, add a new handler and intercept the key
+   press message. Since key presses are passed by pointer, you can modify the
+   keystroke and pass it through to the text field widget.
+   
+   WARNING: in X-Plane before 7.10 (including 6.70) null characters could
+   crash X-Plane. To prevent this, wrap this object with a filter function
+   (more instructions can be found on the SDK website).
+}
+
+
+CONST
+   xpWidgetClass_TextField = 4;
+
+   {
+    Text Field Type Values
+    
+    These control the look of the text field.
+   }
+     { A field for text entry.                                                    }
+      xpTextEntryField                         = 0
+;
+     { A transparent text field. The user can type and the text is drawn, but no  }
+     { background is drawn. You can draw your own background by adding a widget   }
+     { handler and prehandling the draw message.                                  }
+      xpTextTransparent                        = 3
+;
+     { A translucent edit field, dark gray.                                       }
+      xpTextTranslucent                        = 4
+;
+
+   {
+    Text Field Properties
+   }
+     { This is the character position the selection starts at, zero based. If it  }
+     { is the same as the end insertion point, the insertion point is not a       }
+     { selection.                                                                 }
+      xpProperty_EditFieldSelStart             = 1400
+;
+     { This is the character position of the end of the selection.                }
+      xpProperty_EditFieldSelEnd               = 1401
+;
+     { This is the character position a drag was started at if the user is        }
+     { dragging to select text, or -1 if a drag is not in progress.               }
+      xpProperty_EditFieldSelDragStart         = 1402
+;
+     { This is the type of text field to display, from the above list.            }
+      xpProperty_TextFieldType                 = 1403
+;
+     { Set this property to 1 to password protect the field. Characters will be   }
+     { drawn as *s even though the descriptor will contain plain-text.            }
+      xpProperty_PasswordMode                  = 1404
+;
+     { The max number of characters you can enter, if limited.  Zero means        }
+     { unlimited.                                                                 }
+      xpProperty_MaxCharacters                 = 1405
+;
+     { The first visible character on the left.  This effectively scrolls the text}
+     { field.                                                                     }
+      xpProperty_ScrollPosition                = 1406
+;
+     { The font to draw the field's text with.  (An XPLMFontID.)                  }
+      xpProperty_Font                          = 1407
+;
+     { This is the active side of the insert selection.  (Internal)               }
+      xpProperty_ActiveEditSide                = 1408
+;
+
+   {
+    Text Field Messages
+   }
+     { The text field sends this message to itself when its text changes. It sends}
+     { the message up the call chain; param1 is the text field's widget ID.       }
+      xpMsg_TextFieldChanged                   = 1400
+;
+
+{___________________________________________________________________________
+ * SCROLL BAR
+ ___________________________________________________________________________}
+{
+   A standard scroll bar or slider control. The scroll bar has a minimum,
+   maximum and current value that is updated when the user drags it. The
+   scroll bar sends continuous messages as it is dragged.
+}
+
+
+CONST
+   xpWidgetClass_ScrollBar = 5;
+
+   {
+    Scroll Bar Type Values
+    
+    This defines how the scroll bar looks.
+   }
+     { A standard X-Plane scroll bar (with arrows on the ends).                   }
+      xpScrollBarTypeScrollBar                 = 0
+;
+     { A slider, no arrows.                                                       }
+      xpScrollBarTypeSlider                    = 1
+;
+
+   {
+    Scroll Bar Properties
+   }
+     { The current position of the thumb (in between the min and max, inclusive)  }
+      xpProperty_ScrollBarSliderPosition       = 1500
+;
+     { The value the scroll bar has when the thumb is in the lowest position.     }
+      xpProperty_ScrollBarMin                  = 1501
+;
+     { The value the scroll bar has when the thumb is in the highest position.    }
+      xpProperty_ScrollBarMax                  = 1502
+;
+     { How many units to move the scroll bar when clicking next to the thumb. The }
+     { scroll bar always moves one unit when the arrows are clicked.              }
+      xpProperty_ScrollBarPageAmount           = 1503
+;
+     { The type of scrollbar from the enums above.                                }
+      xpProperty_ScrollBarType                 = 1504
+;
+     { Used internally.                                                           }
+      xpProperty_ScrollBarSlop                 = 1505
+;
+
+   {
+    Scroll Bar Messages
+   }
+     { The scroll bar sends this message when the slider position changes. It     }
+     { sends the message up the call chain; param1 is the scroll bar widget ID.   }
+      xpMsg_ScrollBarSliderPositionChanged     = 1500
+;
+
+{___________________________________________________________________________
+ * CAPTION
+ ___________________________________________________________________________}
+{
+   A caption is a simple widget that shows its descriptor as a string, useful
+   for labeling parts of a window. It always shows its descriptor as its
+   string and is otherwise transparent.
+}
+
+
+CONST
+   xpWidgetClass_Caption = 6;
+
+   {
+    Caption Properties
+   }
+     { This property specifies whether the caption is lit; use lit captions       }
+     { against screens.                                                           }
+      xpProperty_CaptionLit                    = 1600
+;
+
+{___________________________________________________________________________
+ * GENERAL GRAPHICS
+ ___________________________________________________________________________}
+{
+   The general graphics widget can show one of many icons available from
+   X-Plane.
+}
+
+
+CONST
+   xpWidgetClass_GeneralGraphics = 7;
+
+   {
+    General Graphics Types Values
+    
+    These define the icon for the general graphics.
+   }
+      xpShip                                   = 4
+;
+      xpILSGlideScope                          = 5
+;
+      xpMarkerLeft                             = 6
+;
+      xp_Airport                               = 7
+;
+      xpNDB                                    = 8
+;
+      xpVOR                                    = 9
+;
+      xpRadioTower                             = 10
+;
+      xpAircraftCarrier                        = 11
+;
+      xpFire                                   = 12
+;
+      xpMarkerRight                            = 13
+;
+      xpCustomObject                           = 14
+;
+      xpCoolingTower                           = 15
+;
+      xpSmokeStack                             = 16
+;
+      xpBuilding                               = 17
+;
+      xpPowerLine                              = 18
+;
+      xpVORWithCompassRose                     = 19
+;
+      xpOilPlatform                            = 21
+;
+      xpOilPlatformSmall                       = 22
+;
+      xpWayPoint                               = 23
+;
+
+   {
+    General Graphics Properties
+   }
+     { This property controls the type of icon that is drawn.                     }
+      xpProperty_GeneralGraphicsType           = 1700
+;
+
+{___________________________________________________________________________
+ * PROGRESS INDICATOR
+ ___________________________________________________________________________}
+{
+   This widget implements a progress indicator as seen when X-Plane starts up.
+}
+
+CONST
+   xpWidgetClass_Progress = 8;
+
+   {
+    Progress Indicator Properties
+   }
+     { This is the current value of the progress indicator.                       }
+      xpProperty_ProgressPosition              = 1800
+;
+     { This is the minimum value, equivalent to 0% filled.                        }
+      xpProperty_ProgressMin                   = 1801
+;
+     { This is the maximum value, equivalent to 100% filled.                      }
+      xpProperty_ProgressMax                   = 1802
+;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/Widgets/XPUIGraphics.pas b/SDK/Delphi/Widgets/XPUIGraphics.pas
new file mode 100644
index 0000000..dee5d23
--- /dev/null
+++ b/SDK/Delphi/Widgets/XPUIGraphics.pas
@@ -0,0 +1,341 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPUIGraphics;
+INTERFACE
+
+USES
+    XPWidgetDefs;
+   {$A4}
+{___________________________________________________________________________
+ * UI GRAPHICS
+ ___________________________________________________________________________}
+
+   {
+    XPWindowStyle
+    
+    There are a few built-in window styles in X-Plane that you can use.
+    
+    Note that X-Plane 6 does not offer real shadow-compositing; you must make
+    sure to put a window on top of another window of the right style to make
+    the shadows work, etc. This applies to elements with insets and shadows.
+    The rules are:
+    
+    Sub windows must go on top of main windows, and screens and list views on
+    top of subwindows. Only help and main windows can be over the main screen.
+    
+    With X-Plane 7 any window or element may be placed over any other element.
+    
+    Some windows are scaled by stretching, some by repeating. The drawing
+    routines know which scaling method to use. The list view cannot be rescaled
+    in X-Plane 6 because it has both a repeating pattern and a gradient in one
+    element. All other elements can be rescaled.
+   }
+TYPE
+   XPWindowStyle = (
+     { An LCD screen that shows help.                                             }
+      xpWindow_Help                            = 0
+ 
+     { A dialog box window.                                                       }
+     ,xpWindow_MainWindow                      = 1
+ 
+     { A panel or frame within a dialog box window.                               }
+     ,xpWindow_SubWindow                       = 2
+ 
+     { An LCD screen within a panel to hold text displays.                        }
+     ,xpWindow_Screen                          = 4
+ 
+     { A list view within a panel for scrolling file names, etc.                  }
+     ,xpWindow_ListView                        = 5
+ 
+   );
+   PXPWindowStyle = ^XPWindowStyle;
+
+   {
+    XPDrawWindow
+    
+    This routine draws a window of the given dimensions at the given offset on
+    the virtual screen in a given style. The window is automatically scaled as
+    appropriate using a bitmap scaling technique (scaling or repeating) as
+    appropriate to the style.
+   }
+   PROCEDURE XPDrawWindow(
+                                        inX1                : Integer;
+                                        inY1                : Integer;
+                                        inX2                : Integer;
+                                        inY2                : Integer;
+                                        inStyle             : XPWindowStyle);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWindowDefaultDimensions
+    
+    This routine returns the default dimensions for a window. Output is either
+    a minimum or fixed value depending on whether the window is scalable.
+   }
+   PROCEDURE XPGetWindowDefaultDimensions(
+                                        inStyle             : XPWindowStyle;
+                                        outWidth            : PInteger;    { Can be nil }
+                                        outHeight           : PInteger);    { Can be nil }
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPElementStyle
+    
+    Elements are individually drawable UI things like push buttons, etc. The
+    style defines what kind of element you are drawing. Elements can be
+    stretched in one or two dimensions (depending on the element). Some
+    elements can be lit.
+    
+    In X-Plane 6 some elements must be drawn over metal. Some are scalable and
+    some are not. Any element can be drawn anywhere in X-Plane 7.
+    
+    Scalable Axis Required Background
+   }
+TYPE
+   XPElementStyle = (
+     { x      metal                                                               }
+      xpElement_TextField                      = 6
+ 
+     { none     metal                                                             }
+     ,xpElement_CheckBox                       = 9
+ 
+     { none     metal                                                             }
+     ,xpElement_CheckBoxLit                    = 10
+ 
+     { none     window header                                                     }
+     ,xpElement_WindowCloseBox                 = 14
+ 
+     { none     window header                                                     }
+     ,xpElement_WindowCloseBoxPressed          = 15
+ 
+     { x     metal                                                                }
+     ,xpElement_PushButton                     = 16
+ 
+     { x     metal                                                                }
+     ,xpElement_PushButtonLit                  = 17
+ 
+     { none     any                                                               }
+     ,xpElement_OilPlatform                    = 24
+ 
+     { none     any                                                               }
+     ,xpElement_OilPlatformSmall               = 25
+ 
+     { none     any                                                               }
+     ,xpElement_Ship                           = 26
+ 
+     { none     any                                                               }
+     ,xpElement_ILSGlideScope                  = 27
+ 
+     { none     any                                                               }
+     ,xpElement_MarkerLeft                     = 28
+ 
+     { none     any                                                               }
+     ,xpElement_Airport                        = 29
+ 
+     { none     any                                                               }
+     ,xpElement_Waypoint                       = 30
+ 
+     { none     any                                                               }
+     ,xpElement_NDB                            = 31
+ 
+     { none     any                                                               }
+     ,xpElement_VOR                            = 32
+ 
+     { none     any                                                               }
+     ,xpElement_RadioTower                     = 33
+ 
+     { none     any                                                               }
+     ,xpElement_AircraftCarrier                = 34
+ 
+     { none     any                                                               }
+     ,xpElement_Fire                           = 35
+ 
+     { none     any                                                               }
+     ,xpElement_MarkerRight                    = 36
+ 
+     { none     any                                                               }
+     ,xpElement_CustomObject                   = 37
+ 
+     { none     any                                                               }
+     ,xpElement_CoolingTower                   = 38
+ 
+     { none     any                                                               }
+     ,xpElement_SmokeStack                     = 39
+ 
+     { none     any                                                               }
+     ,xpElement_Building                       = 40
+ 
+     { none     any                                                               }
+     ,xpElement_PowerLine                      = 41
+ 
+     { none     metal                                                             }
+     ,xpElement_CopyButtons                    = 45
+ 
+     { none     metal                                                             }
+     ,xpElement_CopyButtonsWithEditingGrid     = 46
+ 
+     { x, y     metal                                                             }
+     ,xpElement_EditingGrid                    = 47
+ 
+     { THIS CAN PROBABLY BE REMOVED                                               }
+     ,xpElement_ScrollBar                      = 48
+ 
+     { none     any                                                               }
+     ,xpElement_VORWithCompassRose             = 49
+ 
+     { none     metal                                                             }
+     ,xpElement_Zoomer                         = 51
+ 
+     { x, y     metal                                                             }
+     ,xpElement_TextFieldMiddle                = 52
+ 
+     { none     metal                                                             }
+     ,xpElement_LittleDownArrow                = 53
+ 
+     { none     metal                                                             }
+     ,xpElement_LittleUpArrow                  = 54
+ 
+     { none     metal                                                             }
+     ,xpElement_WindowDragBar                  = 61
+ 
+     { none     metal                                                             }
+     ,xpElement_WindowDragBarSmooth            = 62
+ 
+   );
+   PXPElementStyle = ^XPElementStyle;
+
+   {
+    XPDrawElement
+    
+    XPDrawElement draws a given element at an offset on the virtual screen in
+    set dimensions. Even if the element is not scalable, it will be scaled if
+    the width and height do not match the preferred dimensions; it'll just look
+    ugly. Pass inLit to see the lit version of the element; if the element
+    cannot be lit this is ignored.
+   }
+   PROCEDURE XPDrawElement(
+                                        inX1                : Integer;
+                                        inY1                : Integer;
+                                        inX2                : Integer;
+                                        inY2                : Integer;
+                                        inStyle             : XPElementStyle;
+                                        inLit               : Integer);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetElementDefaultDimensions
+    
+    This routine returns the recommended or minimum dimensions of a given UI
+    element. outCanBeLit tells whether the element has both a lit and unlit
+    state. Pass NULL to not receive any of these parameters.
+   }
+   PROCEDURE XPGetElementDefaultDimensions(
+                                        inStyle             : XPElementStyle;
+                                        outWidth            : PInteger;    { Can be nil }
+                                        outHeight           : PInteger;    { Can be nil }
+                                        outCanBeLit         : PInteger);    { Can be nil }
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPTrackStyle
+    
+    A track is a UI element that displays a value vertically or horizontally.
+    X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars.
+    Tracks can be displayed either horizontally or vertically; tracks will
+    choose their own layout based on the larger dimension of their dimensions
+    (e.g. they know if they are tall or wide). Sliders may be lit or unlit
+    (showing the user manipulating them).
+    
+    - ScrollBar: this is a standard scroll bar with arrows and a thumb to drag.
+    - Slider: this is a simple track with a ball in the middle that can be
+      slid.
+    - Progress: this is a progress indicator showing how a long task is going.
+   }
+TYPE
+   XPTrackStyle = (
+     {  not over metal can be lit  can be rotated                                 }
+      xpTrack_ScrollBar                        = 0
+ 
+     {  over metal  can be lit  can be rotated                                    }
+     ,xpTrack_Slider                           = 1
+ 
+     {  over metal  cannot be lit cannot be rotated                               }
+     ,xpTrack_Progress                         = 2
+ 
+   );
+   PXPTrackStyle = ^XPTrackStyle;
+
+   {
+    XPDrawTrack
+    
+    This routine draws a track. You pass in the track dimensions and size; the
+    track picks the optimal orientation for these dimensions. Pass in the
+    track's minimum current and maximum values; the indicator will be
+    positioned appropriately. You can also specify whether the track is lit or
+    not.
+   }
+   PROCEDURE XPDrawTrack(
+                                        inX1                : Integer;
+                                        inY1                : Integer;
+                                        inX2                : Integer;
+                                        inY2                : Integer;
+                                        inMin               : Integer;
+                                        inMax               : Integer;
+                                        inValue             : Integer;
+                                        inTrackStyle        : XPTrackStyle;
+                                        inLit               : Integer);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetTrackDefaultDimensions
+    
+    This routine returns a track's default smaller dimension; all tracks are
+    scalable in the larger dimension. It also returns whether a track can be
+    lit.
+   }
+   PROCEDURE XPGetTrackDefaultDimensions(
+                                        inStyle             : XPTrackStyle;
+                                        outWidth            : PInteger;
+                                        outCanBeLit         : PInteger);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetTrackMetrics
+    
+    This routine returns the metrics of a track. If you want to write UI code
+    to manipulate a track, this routine helps you know where the mouse
+    locations are. For most other elements, the rectangle the element is drawn
+    in is enough information. However, the scrollbar drawing routine does some
+    automatic placement; this routine lets you know where things ended up. You
+    pass almost everything you would pass to the draw routine. You get out the
+    orientation, and other useful stuff.
+    
+    Besides orientation, you get five dimensions for the five parts of a
+    scrollbar, which are the down button, down area (area before the thumb),
+    the thumb, and the up area and button. For horizontal scrollers, the left
+    button decreases; for vertical scrollers, the top button decreases.
+   }
+   PROCEDURE XPGetTrackMetrics(
+                                        inX1                : Integer;
+                                        inY1                : Integer;
+                                        inX2                : Integer;
+                                        inY2                : Integer;
+                                        inMin               : Integer;
+                                        inMax               : Integer;
+                                        inValue             : Integer;
+                                        inTrackStyle        : XPTrackStyle;
+                                        outIsVertical       : PInteger;
+                                        outDownBtnSize      : PInteger;
+                                        outDownPageSize     : PInteger;
+                                        outThumbSize        : PInteger;
+                                        outUpPageSize       : PInteger;
+                                        outUpBtnSize        : PInteger);
+    cdecl; external XPWIDGETS.DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/Widgets/XPWidgetDefs.pas b/SDK/Delphi/Widgets/XPWidgetDefs.pas
new file mode 100644
index 0000000..bfdb9e0
--- /dev/null
+++ b/SDK/Delphi/Widgets/XPWidgetDefs.pas
@@ -0,0 +1,427 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPWidgetDefs;
+INTERFACE
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * WIDGET DEFINITIONS
+ ___________________________________________________________________________}
+{
+   A widget is a call-back driven screen entity like a push-button, window,
+   text entry field, etc.
+   
+   Use the widget API to create widgets of various classes. You can nest them
+   into trees of widgets to create complex user interfaces.
+}
+
+
+TYPE
+   {
+    XPWidgetID
+    
+    A Widget ID is an opaque unique non-zero handle identifying your widget.
+    Use 0 to specify "no widget". This type is defined as wide enough to hold a
+    pointer. You receive a widget ID when you create a new widget and then use
+    that widget ID to further refer to the widget.
+   }
+   XPWidgetID = pointer;
+   PXPWidgetID = ^XPWidgetID;
+
+   {
+    XPWidgetPropertyID
+    
+    Properties are values attached to instances of your widgets. A property is
+    identified by a 32-bit ID and its value is the width of a pointer.
+    
+    Each widget instance may have a property or not have it. When you set a
+    property on a widget for the first time, the property is added to the
+    widget; it then stays there for the life of the widget.
+    
+    Some property IDs are predefined by the widget package; you can make up
+    your own property IDs as well.
+   }
+   XPWidgetPropertyID = (
+     { A window's refcon is an opaque value used by client code to find other data}
+     { based on it.                                                               }
+      xpProperty_Refcon                        = 0
+ 
+     { These properties are used by the utilities to implement dragging.          }
+     ,xpProperty_Dragging                      = 1
+ 
+     ,xpProperty_DragXOff                      = 2
+ 
+     ,xpProperty_DragYOff                      = 3
+ 
+     { Is the widget highlighted?  (For widgets that support this kind of thing.) }
+     ,xpProperty_Hilited                       = 4
+ 
+     { Is there a C++ object attached to this widget?                             }
+     ,xpProperty_Object                        = 5
+ 
+     { If this property is 1, the widget package will use OpenGL to restrict      }
+     { drawing to the Widget's exposed rectangle.                                 }
+     ,xpProperty_Clip                          = 6
+ 
+     { Is this widget enabled (for those that have a disabled state too)?         }
+     ,xpProperty_Enabled                       = 7
+ 
+     { NOTE: Property IDs 1 - 999 are reserved for the widgets library.           }
+     {                                                                            }
+     { NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes}
+     { provided with the library.                                                 }
+     {                                                                            }
+     { Properties 1000 - 1099 are for widget class 0, 1100 - 1199 for widget class}
+     { 1, etc.                                                                    }
+     ,xpProperty_UserStart                     = 10000
+ 
+   );
+   PXPWidgetPropertyID = ^XPWidgetPropertyID;
+
+   {
+    XPMouseState_t
+    
+    When the mouse is clicked or dragged, a pointer to this structure is passed
+    to your widget function.
+   }
+   XPMouseState_t = RECORD
+     x                        : Integer;
+     y                        : Integer;
+     { Mouse button number, left = 0 (right button not yet supported.             }
+     button                   : Integer;
+{$IFDEF XPLM200}
+     { Scroll wheel delta (button in this case would be the wheel axis number).   }
+     delta                    : Integer;
+{$ENDIF XPLM200}
+   END;
+   PXPMouseState_t = ^XPMouseState_t;
+
+   {
+    XPKeyState_t
+    
+    When a key is pressed, a pointer to this struct is passed to your widget
+    function.
+   }
+   XPKeyState_t = RECORD
+     { The ASCII key that was pressed.  WARNING: this may be 0 for some non-ASCII }
+     { key sequences.                                                             }
+     key                      : XPLMChar;
+     { The flags.  Make sure to check this if you only want key-downs!            }
+     flags                    : XPLMKeyFlags;
+     { The virtual key code for the key                                           }
+     vkey                     : XPLMChar;
+   END;
+   PXPKeyState_t = ^XPKeyState_t;
+
+   {
+    XPWidgetGeometryChange_t
+    
+    This structure contains the deltas for your widget's geometry when it
+    changes.
+   }
+   XPWidgetGeometryChange_t = RECORD
+     dx                       : Integer;
+     { +Y = the widget moved up                                                   }
+     dy                       : Integer;
+     dwidth                   : Integer;
+     dheight                  : Integer;
+   END;
+   PXPWidgetGeometryChange_t = ^XPWidgetGeometryChange_t;
+
+   {
+    XPDispatchMode
+    
+    The dispatching modes describe how the widgets library sends out messages. 
+    Currently there are three modes:
+   }
+   XPDispatchMode = (
+     { The message will only be sent to the target widget.                        }
+      xpMode_Direct                            = 0
+ 
+     { The message is sent to the target widget, then up the chain of parents     }
+     { until the message is handled or a parentless widget is reached.            }
+     ,xpMode_UpChain                           = 1
+ 
+     { The message is sent to the target widget and then all of its children      }
+     { recursively depth-first.                                                   }
+     ,xpMode_Recursive                         = 2
+ 
+     { The message is sent just to the target, but goes to every callback, even if}
+     { it is handled.                                                             }
+     ,xpMode_DirectAllCallbacks                = 3
+ 
+     { The message is only sent to the very first handler even if it is not       }
+     { accepted. (This is really only useful for some internal widget library     }
+     { functions.)                                                                }
+     ,xpMode_Once                              = 4
+ 
+   );
+   PXPDispatchMode = ^XPDispatchMode;
+
+   {
+    XPWidgetClass
+    
+    Widget classes define predefined widget types. A widget class basically
+    specifies from a library the widget function to be used for the widget.
+    Most widgets can be made right from classes.
+   }
+   XPWidgetClass = Integer;
+   PXPWidgetClass = ^XPWidgetClass;
+
+CONST
+    { An unspecified widget class.  Other widget classes are in                  }
+    { XPStandardWidgets.h                                                        }
+   xpWidgetClass_None   = 0;
+
+{___________________________________________________________________________
+ * WIDGET MESSAGES
+ ___________________________________________________________________________}
+
+   {
+    XPWidgetMessage
+    
+    Widgets receive 32-bit messages indicating what action is to be taken or
+    notifications of events. The list of messages may be expanded.
+   }
+TYPE
+   XPWidgetMessage = (
+     { No message, should not be sent.                                            }
+      xpMsg_None                               = 0
+ 
+     { The create message is sent once per widget that is created with your widget}
+     { function and once for any widget that has your widget function attached.   }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: 1 if you are being added as a subclass, 0 if the widget is first  }
+     { being created.                                                             }
+     ,xpMsg_Create                             = 1
+ 
+     { The destroy message is sent once for each message that is destroyed that   }
+     { has your widget function.                                                  }
+     {                                                                            }
+     { Dispatching: Direct for all                                                }
+     {                                                                            }
+     { Param 1: 1 if being deleted by a recursive delete to the parent, 0 for     }
+     { explicit deletion.                                                         }
+     ,xpMsg_Destroy                            = 2
+ 
+     { The paint message is sent to your widget to draw itself. The paint message }
+     { is the bare-bones message; in response you must draw yourself, draw your   }
+     { children, set up clipping and culling, check for visibility, etc. If you   }
+     { don't want to do all of this, ignore the paint message and a draw message  }
+     { (see below) will be sent to you.                                           }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     ,xpMsg_Paint                              = 3
+ 
+     { The draw message is sent to your widget when it is time to draw yourself.  }
+     { OpenGL will be set up to draw in 2-d global screen coordinates, but you    }
+     { should use the XPLM to set up OpenGL state.                                }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     ,xpMsg_Draw                               = 4
+ 
+     { The key press message is sent once per key that is pressed. The first      }
+     { parameter is the type of key code (integer or char) and the second is the  }
+     { code itself. By handling this event, you consume the key stroke.           }
+     {                                                                            }
+     { Handling this message 'consumes' the keystroke; not handling it passes it  }
+     { to your parent widget.                                                     }
+     {                                                                            }
+     { Dispatching: Up Chain                                                      }
+     {                                                                            }
+     { Param 1: A pointer to an XPKeyState_t structure with the keystroke.        }
+     ,xpMsg_KeyPress                           = 5
+ 
+     { Keyboard focus is being given to you. By handling this message you accept  }
+     { keyboard focus. The first parameter will be one if a child of yours gave up}
+     { focus to you, 0 if someone set focus on you explicitly.                    }
+     {                                                                            }
+     { Handling this message accepts focus; not handling refuses focus.           }
+     {                                                                            }
+     { Dispatching: direct                                                        }
+     {                                                                            }
+     { Param 1: 1 if you are gaining focus because your child is giving it up, 0  }
+     { if someone is explicitly giving you focus.                                 }
+     ,xpMsg_KeyTakeFocus                       = 6
+ 
+     { Keyboard focus is being taken away from you. The first parameter will be 1 }
+     { if you are losing focus because another widget is taking it, or 0 if       }
+     { someone called the API to make you lose focus explicitly.                  }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: 1 if focus is being taken by another widget, 0 if code requested  }
+     { to remove focus.                                                           }
+     ,xpMsg_KeyLoseFocus                       = 7
+ 
+     { You receive one mousedown event per click with a mouse-state structure     }
+     { pointed to by parameter 1. By accepting this you eat the click, otherwise  }
+     { your parent gets it. You will not receive drag and mouse up messages if you}
+     { do not accept the down message.                                            }
+     {                                                                            }
+     { Handling this message consumes the mouse click, not handling it passes it  }
+     { to the next widget. You can act 'transparent' as a window by never handling}
+     { moues clicks to certain areas.                                             }
+     {                                                                            }
+     { Dispatching: Up chain NOTE: Technically this is direct dispatched, but the }
+     { widgets library will ship it to each widget until one consumes the click,  }
+     { making it effectively "up chain".                                          }
+     {                                                                            }
+     { Param 1: A pointer to an XPMouseState_t containing the mouse status.       }
+     ,xpMsg_MouseDown                          = 8
+ 
+     { You receive a series of mouse drag messages (typically one per frame in the}
+     { sim) as the mouse is moved once you have accepted a mouse down message.    }
+     { Parameter one points to a mouse-state structure describing the mouse       }
+     { location. You will continue to receive these until the mouse button is     }
+     { released. You may receive multiple mouse state messages with the same mouse}
+     { position. You will receive mouse drag events even if the mouse is dragged  }
+     { out of your current or original bounds at the time of the mouse down.      }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: A pointer to an XPMouseState_t containing the mouse status.       }
+     ,xpMsg_MouseDrag                          = 9
+ 
+     { The mouseup event is sent once when the mouse button is released after a   }
+     { drag or click. You only receive this message if you accept the mouseDown   }
+     { message. Parameter one points to a mouse state structure.                  }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: A pointer to an XPMouseState_t containing the mouse status.       }
+     ,xpMsg_MouseUp                            = 10
+ 
+     { Your geometry or a child's geometry is being changed.                      }
+     {                                                                            }
+     { Dispatching: Up chain                                                      }
+     {                                                                            }
+     { Param 1: The widget ID of the original reshaped target.                    }
+     {                                                                            }
+     { Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the     }
+     { change.                                                                    }
+     ,xpMsg_Reshape                            = 11
+ 
+     { Your exposed area has changed.                                             }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     ,xpMsg_ExposedChanged                     = 12
+ 
+     { A child has been added to you. The child's ID is passed in parameter one.  }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: The Widget ID of the child being added.                           }
+     ,xpMsg_AcceptChild                        = 13
+ 
+     { A child has been removed from you. The child's ID is passed in parameter   }
+     { one.                                                                       }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: The Widget ID of the child being removed.                         }
+     ,xpMsg_LoseChild                          = 14
+ 
+     { You now have a new parent, or have no parent. The parent's ID is passed in,}
+     { or 0 for no parent.                                                        }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: The Widget ID of your parent                                      }
+     ,xpMsg_AcceptParent                       = 15
+ 
+     { You or a child has been shown. Note that this does not include you being   }
+     { shown because your parent was shown, you were put in a new parent, your    }
+     { root was shown, etc.                                                       }
+     {                                                                            }
+     { Dispatching: Up chain                                                      }
+     {                                                                            }
+     { Param 1: The widget ID of the shown widget.                                }
+     ,xpMsg_Shown                              = 16
+ 
+     { You have been hidden. See limitations above.                               }
+     {                                                                            }
+     { Dispatching: Up chain                                                      }
+     {                                                                            }
+     { Param 1: The widget ID of the hidden widget.                               }
+     ,xpMsg_Hidden                             = 17
+ 
+     { Your descriptor has changed.                                               }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     ,xpMsg_DescriptorChanged                  = 18
+ 
+     { A property has changed. Param 1 contains the property ID.                  }
+     {                                                                            }
+     { Dispatching: Direct                                                        }
+     {                                                                            }
+     { Param 1: The Property ID being changed.                                    }
+     {                                                                            }
+     { Param 2: The new property value                                            }
+     ,xpMsg_PropertyChanged                    = 19
+ 
+{$IFDEF XPLM200}
+     { The mouse wheel has moved.                                                 }
+     {                                                                            }
+     { Return 1 to consume the mouse wheel move, or 0 to pass the message to a    }
+     { parent. Dispatching: Up chain                                              }
+     {                                                                            }
+     { Param 1: A pointer to an XPMouseState_t containing the mouse status.       }
+     ,xpMsg_MouseWheel                         = 20
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM200}
+     { The cursor is over your widget. If you consume this message, change the    }
+     { XPLMCursorStatus value to indicate the desired result, with the same rules }
+     { as in XPLMDisplay.h.                                                       }
+     {                                                                            }
+     { Return 1 to consume this message, 0 to pass it on.                         }
+     {                                                                            }
+     { Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct       }
+     { containing the mouse status.                                               }
+     {                                                                            }
+     { Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result   }
+     { you desire.                                                                }
+     ,xpMsg_CursorAdjust                       = 21
+{$ENDIF XPLM200}
+ 
+     { NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes }
+     { provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 }
+     { for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. }
+     ,xpMsg_UserStart                          = 10000
+ 
+   );
+   PXPWidgetMessage = ^XPWidgetMessage;
+
+{___________________________________________________________________________
+ * WIDGET CALLBACK FUNCTION
+ ___________________________________________________________________________}
+
+   {
+    XPWidgetFunc_t
+    
+    This function defines your custom widget's behavior. It will be called by
+    the widgets library to send messages to your widget. The message and widget
+    ID are passed in, as well as two pointer-width signed parameters whose
+    meaning varies with the message. Return 1 to indicate that you have
+    processed the message, 0 to indicate that you have not. For any message
+    that is not understood, return 0.
+   }
+TYPE
+     XPWidgetFunc_t = FUNCTION(
+                                    inMessage           : XPWidgetMessage;
+                                    inWidget            : XPWidgetID;
+                                    inParam1            : intptr_t;
+                                    inParam2            : intptr_t) : Integer; cdecl;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/Widgets/XPWidgetUtils.pas b/SDK/Delphi/Widgets/XPWidgetUtils.pas
new file mode 100644
index 0000000..f6518b8
--- /dev/null
+++ b/SDK/Delphi/Widgets/XPWidgetUtils.pas
@@ -0,0 +1,198 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPWidgetUtils;
+INTERFACE
+{
+   ## USAGE NOTES
+   
+   The XPWidgetUtils library contains useful functions that make writing and
+   using widgets less of a pain.
+   
+   One set of functions are the widget behavior functions. These functions
+   each add specific useful behaviors to widgets. They can be used in two
+   manners:
+   
+   1. You can add a widget behavior function to a widget as a callback proc
+      using the XPAddWidgetCallback function. The widget will gain that
+      behavior. Remember that the last function you add has highest priority.
+      You can use this to change or augment the behavior of an existing
+      finished widget.
+   
+   2. You can call a widget function from inside your own widget function.
+      This allows you to include useful behaviors in custom-built widgets. A
+      number of the standard widgets get their behavior from this library. To
+      do this, call the behavior function from your function first. If it
+      returns 1, that means it handled the event and you don't need to; simply
+      return 1.
+}
+
+USES
+    XPWidgetDefs;
+   {$A4}
+{___________________________________________________________________________
+ * GENERAL UTILITIES
+ ___________________________________________________________________________}
+
+
+   {
+    XPWidgetCreate_t
+    
+    This structure contains all of the parameters needed to create a widget. It
+    is used with XPUCreateWidgets to create widgets in bulk from an array. All
+    parameters correspond to those of XPCreateWidget except for the container
+    index.
+    
+    If the container index is equal to the index of a widget in the array, the
+    widget in the array passed to XPUCreateWidgets is used as the parent of
+    this widget. Note that if you pass an index greater than your own position
+    in the array, the parent you are requesting will not exist yet.
+    
+    If the container index is NO_PARENT, the parent widget is specified as
+    NULL. If the container index is PARAM_PARENT, the widget passed into
+    XPUCreateWidgets is used.
+   }
+TYPE
+   XPWidgetCreate_t = RECORD
+     left                     : Integer;
+     top                      : Integer;
+     right                    : Integer;
+     bottom                   : Integer;
+     visible                  : Integer;
+     descriptor               : XPLMString;
+     { Whether this widget is a root widget                                       }
+     isRoot                   : Integer;
+     { The index of the widget to be contained within, or a constant              }
+     containerIndex           : Integer;
+     widgetClass              : XPWidgetClass;
+   END;
+   PXPWidgetCreate_t = ^XPWidgetCreate_t;
+
+CONST
+   NO_PARENT            = -1;
+
+   PARAM_PARENT         = -2;
+
+
+   {
+    XPUCreateWidgets
+    
+    This function creates a series of widgets from a table (see
+    XPCreateWidget_t above). Pass in an array of widget creation structures and
+    an array of widget IDs that will receive each widget.
+    
+    Widget parents are specified by index into the created widget table,
+    allowing you to create nested widget structures. You can create multiple
+    widget trees in one table. Generally you should create widget trees from
+    the top down.
+    
+    You can also pass in a widget ID that will be used when the widget's parent
+    is listed as PARAM_PARENT; this allows you to embed widgets created with
+    XPUCreateWidgets in a widget created previously.
+   }
+   PROCEDURE XPUCreateWidgets(
+                                        inWidgetDefs        : PXPWidgetCreate_t;
+                                        inCount             : Integer;
+                                        inParamParent       : XPWidgetID;
+                                        ioWidgets           : PXPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPUMoveWidgetBy
+    
+    Simply moves a widget by an amount, +x = right, +y = up, without resizing
+    the widget.
+   }
+   PROCEDURE XPUMoveWidgetBy(
+                                        inWidget            : XPWidgetID;
+                                        inDeltaX            : Integer;
+                                        inDeltaY            : Integer);
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * LAYOUT MANAGERS
+ ___________________________________________________________________________}
+{
+   The layout managers are widget behavior functions for handling where
+   widgets move. Layout managers can be called from a widget function or
+   attached to a widget later.
+}
+
+
+   {
+    XPUFixedLayout
+    
+    This function causes the widget to maintain its children in fixed position
+    relative to itself as it is resized. Use this on the top level 'window'
+    widget for your window.
+   }
+   FUNCTION XPUFixedLayout(
+                                        inMessage           : XPWidgetMessage;
+                                        inWidget            : XPWidgetID;
+                                        inParam1            : intptr_t;
+                                        inParam2            : intptr_t) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * WIDGET PROC BEHAVIORS
+ ___________________________________________________________________________}
+{
+   These widget behavior functions add other useful behaviors to widgets.
+   These functions cannot be attached to a widget; they must be called from
+   your widget function.
+}
+
+
+   {
+    XPUSelectIfNeeded
+    
+    This causes the widget to bring its window to the foreground if it is not
+    already. inEatClick specifies whether clicks in the background should be
+    consumed by bringing the window to the foreground.
+   }
+   FUNCTION XPUSelectIfNeeded(
+                                        inMessage           : XPWidgetMessage;
+                                        inWidget            : XPWidgetID;
+                                        inParam1            : intptr_t;
+                                        inParam2            : intptr_t;
+                                        inEatClick          : Integer) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPUDefocusKeyboard
+    
+    This causes the widget to send keyboard focus back to X-Plane. This stops
+    editing of any text fields, etc.
+   }
+   FUNCTION XPUDefocusKeyboard(
+                                        inMessage           : XPWidgetMessage;
+                                        inWidget            : XPWidgetID;
+                                        inParam1            : intptr_t;
+                                        inParam2            : intptr_t;
+                                        inEatClick          : Integer) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPUDragWidget
+    
+    XPUDragWidget drags the widget in response to mouse clicks. Pass in not
+    only the event, but the global coordinates of the drag region, which might
+    be a sub-region of your widget (for example, a title bar).
+   }
+   FUNCTION XPUDragWidget(
+                                        inMessage           : XPWidgetMessage;
+                                        inWidget            : XPWidgetID;
+                                        inParam1            : intptr_t;
+                                        inParam2            : intptr_t;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/Widgets/XPWidgets.pas b/SDK/Delphi/Widgets/XPWidgets.pas
new file mode 100644
index 0000000..5f5b217
--- /dev/null
+++ b/SDK/Delphi/Widgets/XPWidgets.pas
@@ -0,0 +1,528 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPWidgets;
+INTERFACE
+{
+   ## THEORY OF OPERATION AND NOTES
+   
+   Widgets are persistent view 'objects' for X-Plane. A widget is an object
+   referenced by its opaque handle (widget ID) and the APIs in this file. You
+   cannot access the widget's guts directly. Every Widget has the following
+   intrinsic data:
+   
+   - A bounding box defined in global screen coordinates with 0,0 in the
+     bottom left and +y = up, +x = right.
+   - A visible box, which is the intersection of the bounding box with the
+     widget's parents visible box.
+   - Zero or one parent widgets. (Always zero if the widget is a root widget.
+   - Zero or more child widgets.
+   - Whether the widget is a root. Root widgets are the top level plugin
+     windows.
+   - Whether the widget is visible.
+   - A text string descriptor, whose meaning varies from widget to widget.
+   - An arbitrary set of 32 bit integral properties defined by 32-bit integral
+     keys. This is how specific widgets store specific data.
+   - A list of widget callback procedures that implements the widgets
+     behaviors.
+   
+   The Widgets library sends messages to widgets to request specific behaviors
+   or notify the widget of things.
+   
+   Widgets may have more than one callback function, in which case messages
+   are sent to the most recently added callback function until the message is
+   handled. Messages may also be sent to parents or children; see the
+   XPWidgetDefs.h header file for the different widget message dispatching
+   functions. By adding a callback function to a window you can 'subclass' its
+   behavior.
+   
+   A set of standard widgets are provided that serve common UI purposes. You
+   can also customize or implement entirely custom widgets.
+   
+   Widgets are different than other view hierarchies (most notably Win32,
+   which they bear a striking resemblance to) in the following ways:
+   
+   - Not all behavior can be patched. State that is managed by the XPWidgets
+     DLL and not by individual widgets cannot be customized.
+   - All coordinates are in global screen coordinates. Coordinates are not
+     relative to an enclosing widget, nor are they relative to a display
+     window.
+   - Widget messages are always dispatched synchronously, and there is no
+     concept of scheduling an update or a dirty region. Messages originate
+     from X-Plane as the sim cycle goes by. Since X-Plane is constantly
+     redrawing, so are widgets; there is no need to mark a part of a widget as
+     'needing redrawing' because redrawing happens frequently whether the
+     widget needs it or not.
+   - Any widget may be a 'root' widget, causing it to be drawn; there is no
+     relationship between widget class and rootness. Root widgets are
+     implemented as XPLMDisplay windows.
+}
+
+USES
+    XPWidgetDefs, XPLMDisplay;
+   {$A4}
+{___________________________________________________________________________
+ * WIDGET CREATION AND MANAGEMENT
+ ___________________________________________________________________________}
+
+   {
+    XPCreateWidget
+    
+    This function creates a new widget and returns the new widget's ID to you.
+    If the widget creation fails for some reason, it returns NULL. Widget
+    creation will fail either if you pass a bad class ID or if there is not
+    adequate memory.
+    
+    Input Parameters:
+    
+    - Top, left, bottom, and right in global screen coordinates defining the
+      widget's location on the screen.
+    - inVisible is 1 if the widget should be drawn, 0 to start the widget as
+      hidden.
+    - inDescriptor is a null terminated string that will become the widget's
+      descriptor.
+    - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be.
+    - inContainer is the ID of this widget's container. It must be 0 for a root
+      widget. For a non-root widget, pass the widget ID of the widget to place
+      this widget within. If this widget is not going to start inside another
+      widget, pass 0; this new widget will be created but will not be drawn
+      until it is placed inside another widget.
+    - inClass is the class of the widget to draw. Use one of the predefined
+      class-IDs to create a standard widget.
+    
+    A note on widget embedding: a widget is only called (and will be drawn,
+    etc.) if it is placed within a widget that will be called. Root widgets are
+    always called. So it is possible to have whole chains of widgets that are
+    simply not called. You can preconstruct widget trees and then place them
+    into root widgets later to activate them if you wish.
+   }
+   FUNCTION XPCreateWidget(
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer;
+                                        inVisible           : Integer;
+                                        inDescriptor        : XPLMString;
+                                        inIsRoot            : Integer;
+                                        inContainer         : XPWidgetID;
+                                        inClass             : XPWidgetClass) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPCreateCustomWidget
+    
+    This function is the same as XPCreateWidget except that instead of passing
+    a class ID, you pass your widget callback function pointer defining the
+    widget. Use this function to define a custom widget. All parameters are the
+    same as XPCreateWidget, except that the widget class has been replaced with
+    the widget function.
+   }
+   FUNCTION XPCreateCustomWidget(
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer;
+                                        inVisible           : Integer;
+                                        inDescriptor        : XPLMString;
+                                        inIsRoot            : Integer;
+                                        inContainer         : XPWidgetID;
+                                        inCallback          : XPWidgetFunc_t) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPDestroyWidget
+    
+    This class destroys a widget. Pass in the ID of the widget to kill. If you
+    pass 1 for inDestroyChilren, the widget's children will be destroyed first,
+    then this widget will be destroyed. (Furthermore, the widget's children
+    will be destroyed with the inDestroyChildren flag set to 1, so the
+    destruction will recurse down the widget tree.) If you pass 0 for this
+    flag, direct child widgets will simply end up with their parent set to 0.
+   }
+   PROCEDURE XPDestroyWidget(
+                                        inWidget            : XPWidgetID;
+                                        inDestroyChildren   : Integer);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPSendMessageToWidget
+    
+    This sends any message to a widget. You should probably not go around
+    simulating the predefined messages that the widgets library defines for
+    you. You may however define custom messages for your widgets and send them
+    with this method.
+    
+    This method supports several dispatching patterns; see XPDispatchMode for
+    more info. The function returns 1 if the message was handled, 0 if it was
+    not.
+    
+    For each widget that receives the message (see the dispatching modes), each
+    widget function from the most recently installed to the oldest one receives
+    the message in order until it is handled.
+   }
+   FUNCTION XPSendMessageToWidget(
+                                        inWidget            : XPWidgetID;
+                                        inMessage           : XPWidgetMessage;
+                                        inMode              : XPDispatchMode;
+                                        inParam1            : intptr_t;
+                                        inParam2            : intptr_t) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * WIDGET POSITIONING AND VISIBILITY
+ ___________________________________________________________________________}
+
+   {
+    XPPlaceWidgetWithin
+    
+    This function changes which container a widget resides in. You may NOT use
+    this function on a root widget! inSubWidget is the widget that will be
+    moved. Pass a widget ID in inContainer to make inSubWidget be a child of
+    inContainer. It will become the last/closest widget in the container. Pass
+    0 to remove the widget from any container. Any call to this other than
+    passing the widget ID of the old parent of the affected widget will cause
+    the widget to be removed from its old parent. Placing a widget within its
+    own parent simply makes it the last widget.
+    
+    NOTE: this routine does not reposition the sub widget in global
+    coordinates. If the container has layout management code, it will
+    reposition the subwidget for you, otherwise you must do it with
+    SetWidgetGeometry.
+   }
+   PROCEDURE XPPlaceWidgetWithin(
+                                        inSubWidget         : XPWidgetID;
+                                        inContainer         : XPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPCountChildWidgets
+    
+    This routine returns the number of widgets another widget contains.
+   }
+   FUNCTION XPCountChildWidgets(
+                                        inWidget            : XPWidgetID) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetNthChildWidget
+    
+    This routine returns the widget ID of a child widget by index. Indexes are
+    0 based, from 0 to the number of widgets in the parentone minus one,
+    inclusive. If the index is invalid, 0 is returned.
+   }
+   FUNCTION XPGetNthChildWidget(
+                                        inWidget            : XPWidgetID;
+                                        inIndex             : Integer) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetParentWidget
+    
+    Returns the parent of a widget, or 0 if the widget has no parent. Root
+    widgets never have parents and therefore always return 0.
+   }
+   FUNCTION XPGetParentWidget(
+                                        inWidget            : XPWidgetID) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPShowWidget
+    
+    This routine makes a widget visible if it is not already. Note that if a
+    widget is not in a rooted widget hierarchy or one of its parents is not
+    visible, it will still not be visible to the user.
+   }
+   PROCEDURE XPShowWidget(
+                                        inWidget            : XPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPHideWidget
+    
+    Makes a widget invisible. See XPShowWidget for considerations of when a
+    widget might not be visible despite its own visibility state.
+   }
+   PROCEDURE XPHideWidget(
+                                        inWidget            : XPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPIsWidgetVisible
+    
+    This returns 1 if a widget is visible, 0 if it is not. Note that this
+    routine takes into consideration whether a parent is invisible. Use this
+    routine to tell if the user can see the widget.
+   }
+   FUNCTION XPIsWidgetVisible(
+                                        inWidget            : XPWidgetID) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPFindRootWidget
+    
+    Returns the Widget ID of the root widget that contains the passed in widget
+    or NULL if the passed in widget is not in a rooted hierarchy.
+   }
+   FUNCTION XPFindRootWidget(
+                                        inWidget            : XPWidgetID) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPBringRootWidgetToFront
+    
+    This routine makes the specified widget be in the frontmost widget
+    hierarchy. If this widget is a root widget, its widget hierarchy comes to
+    front, otherwise the widget's root is brought to the front. If this widget
+    is not in an active widget hiearchy (e.g. there is no root widget at the
+    top of the tree), this routine does nothing.
+   }
+   PROCEDURE XPBringRootWidgetToFront(
+                                        inWidget            : XPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPIsWidgetInFront
+    
+    This routine returns true if this widget's hierarchy is the frontmost
+    hierarchy. It returns false if the widget's hierarchy is not in front, or
+    if the widget is not in a rooted hierarchy.
+   }
+   FUNCTION XPIsWidgetInFront(
+                                        inWidget            : XPWidgetID) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetGeometry
+    
+    This routine returns the bounding box of a widget in global coordinates.
+    Pass NULL for any parameter you are not interested in.
+   }
+   PROCEDURE XPGetWidgetGeometry(
+                                        inWidget            : XPWidgetID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPSetWidgetGeometry
+    
+    This function changes the bounding box of a widget.
+   }
+   PROCEDURE XPSetWidgetGeometry(
+                                        inWidget            : XPWidgetID;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetForLocation
+    
+    Given a widget and a location, this routine returns the widget ID of the
+    child of that widget that owns that location. If inRecursive is true then
+    this will return a child of a child of a widget as it tries to find the
+    deepest widget at that location. If inVisibleOnly is true, then only
+    visible widgets are considered, otherwise all widgets are considered. The
+    widget ID passed for inContainer will be returned if the location is in
+    that widget but not in a child widget. 0 is returned if the location is not
+    in the container.
+    
+    NOTE: if a widget's geometry extends outside its parents geometry, it will
+    not be returned by this call for mouse locations outside the parent
+    geometry. The parent geometry limits the child's eligibility for mouse
+    location.
+   }
+   FUNCTION XPGetWidgetForLocation(
+                                        inContainer         : XPWidgetID;
+                                        inXOffset           : Integer;
+                                        inYOffset           : Integer;
+                                        inRecursive         : Integer;
+                                        inVisibleOnly       : Integer) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetExposedGeometry
+    
+    This routine returns the bounds of the area of a widget that is completely
+    within its parent widgets. Since a widget's bounding box can be outside its
+    parent, part of its area will not be eligible for mouse clicks and should
+    not draw. Use XPGetWidgetGeometry to find out what area defines your
+    widget's shape, but use this routine to find out what area to actually draw
+    into. Note that the widget library does not use OpenGL clipping to keep
+    frame rates up, although you could use it internally.
+   }
+   PROCEDURE XPGetWidgetExposedGeometry(
+                                        inWidgetID          : XPWidgetID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * ACCESSING WIDGET DATA
+ ___________________________________________________________________________}
+
+   {
+    XPSetWidgetDescriptor
+    
+    Every widget has a descriptor, which is a text string. What the text string
+    is used for varies from widget to widget; for example, a push button's text
+    is its descriptor, a caption shows its descriptor, and a text field's
+    descriptor is the text being edited. In other words, the usage for the text
+    varies from widget to widget, but this API provides a universal and
+    convenient way to get at it. While not all UI widgets need their
+    descriptor, many do.
+   }
+   PROCEDURE XPSetWidgetDescriptor(
+                                        inWidget            : XPWidgetID;
+                                        inDescriptor        : XPLMString);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetDescriptor
+    
+    This routine returns the widget's descriptor. Pass in the length of the
+    buffer you are going to receive the descriptor in. The descriptor will be
+    null terminated for you. This routine returns the length of the actual
+    descriptor; if you pass NULL for outDescriptor, you can get the
+    descriptor's length without getting its text. If the length of the
+    descriptor exceeds your buffer length, the buffer will not be null
+    terminated (this routine has 'strncpy' semantics).
+   }
+   FUNCTION XPGetWidgetDescriptor(
+                                        inWidget            : XPWidgetID;
+                                        outDescriptor       : XPLMString;
+                                        inMaxDescLength     : Integer) : Integer;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetUnderlyingWindow
+    
+    Returns the window (from the XPLMDisplay API) that backs your widget
+    window. If you have opted in to modern windows, via a call to
+    XPLMEnableFeature("XPLM_USE_NATIVE_WIDGET_WINDOWS", 1), you can use the
+    returned window ID for display APIs like XPLMSetWindowPositioningMode(),
+    allowing you to pop the widget window out into a real OS window, or move it
+    into VR.
+   }
+   FUNCTION XPGetWidgetUnderlyingWindow(
+                                        inWidget            : XPWidgetID) : XPLMWindowID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPSetWidgetProperty
+    
+    This function sets a widget's property. Properties are arbitrary values
+    associated by a widget by ID.
+   }
+   PROCEDURE XPSetWidgetProperty(
+                                        inWidget            : XPWidgetID;
+                                        inProperty          : XPWidgetPropertyID;
+                                        inValue             : intptr_t);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetProperty
+    
+    This routine returns the value of a widget's property, or 0 if the property
+    is not defined. If you need to know whether the property is defined, pass a
+    pointer to an int for inExists; the existence of that property will be
+    returned in the int. Pass NULL for inExists if you do not need this
+    information.
+   }
+   FUNCTION XPGetWidgetProperty(
+                                        inWidget            : XPWidgetID;
+                                        inProperty          : XPWidgetPropertyID;
+                                        inExists            : PInteger) : intptr_t;    { Can be nil }
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * KEYBOARD MANAGEMENT
+ ___________________________________________________________________________}
+
+   {
+    XPSetKeyboardFocus
+    
+    Controls which widget will receive keystrokes. Pass the widget ID of the
+    widget to get the keys. Note that if the widget does not care about
+    keystrokes, they will go to the parent widget, and if no widget cares about
+    them, they go to X-Plane.
+    
+    If you set the keyboard focus to widget ID 0, X-Plane gets keyboard focus.
+    
+    This routine returns the widget ID that ended up with keyboard focus, or 0
+    for X-Plane.
+    
+    Keyboard focus is not changed if the new widget will not accept it. For
+    setting to X-Plane, keyboard focus is always accepted.
+   }
+   FUNCTION XPSetKeyboardFocus(
+                                        inWidget            : XPWidgetID) : XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPLoseKeyboardFocus
+    
+    This causes the specified widget to lose focus; focus is passed to its
+    parent, or the next parent that will accept it. This routine does nothing
+    if this widget does not have focus.
+   }
+   PROCEDURE XPLoseKeyboardFocus(
+                                        inWidget            : XPWidgetID);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetWithFocus
+    
+    This routine returns the widget that has keyboard focus, or 0 if X-Plane
+    has keyboard focus or some other plugin window that does not have widgets
+    has focus.
+   }
+   FUNCTION XPGetWidgetWithFocus: XPWidgetID;
+    cdecl; external XPWIDGETS.DLL;
+
+{___________________________________________________________________________
+ * CREATING CUSTOM WIDGETS
+ ___________________________________________________________________________}
+
+   {
+    XPAddWidgetCallback
+    
+    This function adds a new widget callback to a widget. This widget callback
+    supercedes any existing ones and will receive messages first; if it does
+    not handle messages they will go on to be handled by pre-existing widgets.
+    
+    The widget function will remain on the widget for the life of the widget.
+    The creation message will be sent to the new callback immediately with the
+    widget ID, and the destruction message will be sent before the other widget
+    function receives a destruction message.
+    
+    This provides a way to 'subclass' an existing widget. By providing a second
+    hook that only handles certain widget messages, you can customize or extend
+    widget behavior.
+   }
+   PROCEDURE XPAddWidgetCallback(
+                                        inWidget            : XPWidgetID;
+                                        inNewCallback       : XPWidgetFunc_t);
+    cdecl; external XPWIDGETS.DLL;
+
+   {
+    XPGetWidgetClassFunc
+    
+    Given a widget class, this function returns the callbacks that power that
+    widget class.
+   }
+   FUNCTION XPGetWidgetClassFunc(
+                                        inWidgetClass       : XPWidgetClass) : XPWidgetFunc_t;
+    cdecl; external XPWIDGETS.DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMCamera.pas b/SDK/Delphi/XPLM/XPLMCamera.pas
new file mode 100644
index 0000000..87ecbc0
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMCamera.pas
@@ -0,0 +1,155 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMCamera;
+INTERFACE
+{
+   The XPLMCamera APIs allow plug-ins to control the camera angle in X-Plane.
+   This has a number of applications, including but not limited to:
+   
+   - Creating new views (including dynamic/user-controllable views) for the
+     user.
+   - Creating applications that use X-Plane as a renderer of scenery,
+     aircrafts, or both.
+   
+   The camera is controlled via six parameters: a location in OpenGL
+   coordinates and pitch, roll and yaw, similar to an airplane's position.
+   OpenGL coordinate info is described in detail in the XPLMGraphics
+   documentation; generally you should use the XPLMGraphics routines to
+   convert from world to local coordinates. The camera's orientation starts
+   facing level with the ground directly up the negative-Z axis (approximately
+   north) with the horizon horizontal. It is then rotated clockwise for yaw,
+   pitched up for positive pitch, and rolled clockwise around the vector it is
+   looking along for roll.
+   
+   You control the camera either either until the user selects a new view or
+   permanently (the latter being similar to how UDP camera control works). You
+   control the camera by registering a callback per frame from which you
+   calculate the new camera positions. This guarantees smooth camera motion.
+   
+   Use the XPLMDataAccess APIs to get information like the position of the
+   aircraft, etc. for complex camera positioning.
+   
+   Note: if your goal is to move the virtual pilot in the cockpit, this API is
+   not needed; simply update the datarefs for the pilot's head position.
+   
+   For custom exterior cameras, set the camera's mode to an external view
+   first to get correct sound and 2-d panel behavior.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * CAMERA CONTROL
+ ___________________________________________________________________________}
+
+   {
+    XPLMCameraControlDuration
+    
+    This enumeration states how long you want to retain control of the camera.
+    You can retain it indefinitely or until the user selects a new view.
+   }
+TYPE
+   XPLMCameraControlDuration = (
+     { Control the camera until the user picks a new view.                        }
+      xplm_ControlCameraUntilViewChanges       = 1
+ 
+     { Control the camera until your plugin is disabled or another plugin forcibly}
+     { takes control.                                                             }
+     ,xplm_ControlCameraForever                = 2
+ 
+   );
+   PXPLMCameraControlDuration = ^XPLMCameraControlDuration;
+
+   {
+    XPLMCameraPosition_t
+    
+    This structure contains a full specification of the camera. X, Y, and Z are
+    the camera's position in OpenGL coordinates; pitch, roll, and yaw are
+    rotations from a camera facing flat north in degrees. Positive pitch means
+    nose up, positive roll means roll right, and positive yaw means yaw right,
+    all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0
+    magnifying by 2x (objects appear larger).
+   }
+   XPLMCameraPosition_t = RECORD
+     x                        : Single;
+     y                        : Single;
+     z                        : Single;
+     pitch                    : Single;
+     heading                  : Single;
+     roll                     : Single;
+     zoom                     : Single;
+   END;
+   PXPLMCameraPosition_t = ^XPLMCameraPosition_t;
+
+   {
+    XPLMCameraControl_f
+    
+    You use an XPLMCameraControl function to provide continuous control over
+    the camera. You are passed a structure in which to put the new camera
+    position; modify it and return 1 to reposition the camera. Return 0 to
+    surrender control of the camera; camera control will be handled by X-Plane
+    on this draw loop. The contents of the structure as you are called are
+    undefined.
+    
+    If X-Plane is taking camera control away from you, this function will be
+    called with inIsLosingControl set to 1 and ioCameraPosition NULL.
+   }
+     XPLMCameraControl_f = FUNCTION(
+                                    outCameraPosition   : PXPLMCameraPosition_t;    { Can be nil }
+                                    inIsLosingControl   : Integer;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+   {
+    XPLMControlCamera
+    
+    This function repositions the camera on the next drawing cycle. You must
+    pass a non-null control function. Specify in inHowLong how long you'd like
+    control (indefinitely or until a new view mode is set by the user).
+   }
+   PROCEDURE XPLMControlCamera(
+                                        inHowLong           : XPLMCameraControlDuration;
+                                        inControlFunc       : XPLMCameraControl_f;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDontControlCamera
+    
+    This function stops you from controlling the camera. If you have a camera
+    control function, it will not be called with an inIsLosingControl flag.
+    X-Plane will control the camera on the next cycle.
+    
+    For maximum compatibility you should not use this routine unless you are in
+    posession of the camera.
+   }
+   PROCEDURE XPLMDontControlCamera;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMIsCameraBeingControlled
+    
+    This routine returns 1 if the camera is being controlled, zero if it is
+    not. If it is and you pass in a pointer to a camera control duration, the
+    current control duration will be returned.
+   }
+   FUNCTION XPLMIsCameraBeingControlled(
+                                        outCameraControlDuration: PXPLMCameraControlDuration) : Integer;    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMReadCameraPosition
+    
+    This function reads the current camera position.
+   }
+   PROCEDURE XPLMReadCameraPosition(
+                                        outCameraPosition   : PXPLMCameraPosition_t);
+    cdecl; external XPLM_DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMDataAccess.pas b/SDK/Delphi/XPLM/XPLMDataAccess.pas
new file mode 100644
index 0000000..f4d3a28
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMDataAccess.pas
@@ -0,0 +1,773 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMDataAccess;
+INTERFACE
+{
+   The data access API gives you a generic, flexible, high performance way to
+   read and write data to and from X-Plane and other plug-ins. For example,
+   this API allows you to read and set the nav radios, get the plane location,
+   determine the current effective graphics frame rate, etc.
+   
+   The data access APIs are the way that you read and write data from the sim
+   as well as other plugins.
+   
+   The API works using opaque data references. A data reference is a source of
+   data; you do not know where it comes from, but once you have it you can
+   read the data quickly and possibly write it.
+   
+   Dataref Lookup
+   --------------
+   
+   Data references are identified by verbose, permanent string names; by
+   convention these names use path separators to form a hierarchy of datarefs,
+   e.g. (sim/cockpit/radios/nav1_freq_hz). The actual opaque numeric value of
+   the data reference, as returned by the XPLM API, is implementation defined
+   and changes each time X-Plane is launched; therefore you need to look up
+   the dataref by path every time your plugin runs.
+   
+   The task of looking up a data reference is relatively expensive; look up
+   your data references once based on the verbose path strings, and save the
+   opaque data reference value for the duration of your plugin's operation.
+   Reading and writing data references is relatively fast (the cost is
+   equivalent to two function calls through function pointers).
+   
+   X-Plane publishes many thousands of datarefs; a complete list may be found
+   in the reference section of the SDK online documentation (from the SDK home
+   page, choose Documentation) and the Resources/plugins/DataRefs.txt file.
+   
+   Dataref Types
+   -------------
+   
+   A note on typing: you must know the correct data type to read and write.
+   APIs are provided for reading and writing data in a number of ways. You can
+   also double check the data type for a dataref. Automatic type conversion is
+   not done for you.
+   
+   Dataref types are a set, e.g. a dataref can be more than one type.  When
+   this happens, you can choose which API you want to use to read.  For
+   example, it is not uncommon for a dataref to be available both as float and
+   double.  This means you can use either XPLMGetDatad or XPLMGetDataf to read
+   it.
+   
+   Creating New Datarefs
+   ---------------------
+   
+   X-Plane provides datarefs that come with the sim, but plugins can also
+   create their own datarefs.  A plugin creates a dataref by registering
+   function callbacks to read and write the dataref.  The XPLM will call your
+   plugin each time some other plugin (or X-Plane) tries to read or write the
+   dataref.  You must provide a read (and optional write) callback for each
+   data type you support.
+   
+   A note for plugins sharing data with other plugins: the load order of
+   plugins is not guaranteed. To make sure that every plugin publishing data
+   has published their data references before other plugins try to subscribe,
+   publish your data references in your start routine but resolve others'
+   datarefs the first time your 'enable' routine is called, or the first time
+   they are needed in code.
+   
+   When a plugin that created a dataref is unloaded, it becomes "orphaned". 
+   The dataref handle continues to be usable, but the dataref is not writable,
+   and reading it will always return 0 (or 0 items for arrays).  If the plugin
+   is reloaded and re-registers the dataref, the handle becomes un-orphaned
+   and works again.
+   
+   Introspection: Finding All Datarefs
+   -----------------------------------
+   
+   In the XPLM400 API, it is possible for a plugin to iterate the entire set
+   of datarefs. This functionality is meant only for "tool" add-ons, like
+   dataref browsers; normally all add-ons  should find the dataref they want
+   by name.
+   
+   Because datarefs are never destroyed during a run of the simulator (they
+   are orphaned when their providing plugin goes away until a new one
+   re-registers the dataref), the set of  datarefs for a given run of X-Plane
+   can be enumerated by index. A plugin that wants to find all new datarefs
+   can use XPLMCountDataRefs to find the number of datarefs and iterate only 
+   the ones with higher index numbers than the last iteration.
+   
+   Plugins can also receive notifications when datarefs are registered; see
+   the XPLMPlugin feature-enable API for more details.    
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * READING AND WRITING DATA
+ ___________________________________________________________________________}
+{
+   These routines allow you to access data from within X-Plane and sometimes
+   modify it.
+}
+
+
+TYPE
+   {
+    XPLMDataRef
+    
+    A dataref is an opaque handle to data provided by the simulator or another
+    plugin. It uniquely identifies one variable (or array of variables) over
+    the lifetime of your plugin. You never hard code these values; you always
+    get them from XPLMFindDataRef.
+   }
+   XPLMDataRef = pointer;
+   PXPLMDataRef = ^XPLMDataRef;
+
+   {
+    XPLMDataTypeID
+    
+    This is an enumeration that defines the type of the data behind a data
+    reference. This allows you to sanity check that the data type matches what
+    you expect. But for the most part, you will know the type of data you are
+    expecting from the online documentation.
+    
+    Data types each take a bit field; it is legal to have a single dataref be
+    more than one type of data.  Whe this happens, you can pick any matching
+    get/set API.
+   }
+   XPLMDataTypeID = (
+     { Data of a type the current XPLM doesn't do.                                }
+      xplmType_Unknown                         = 0
+ 
+     { A single 4-byte integer, native endian.                                    }
+     ,xplmType_Int                             = 1
+ 
+     { A single 4-byte float, native endian.                                      }
+     ,xplmType_Float                           = 2
+ 
+     { A single 8-byte double, native endian.                                     }
+     ,xplmType_Double                          = 4
+ 
+     { An array of 4-byte floats, native endian.                                  }
+     ,xplmType_FloatArray                      = 8
+ 
+     { An array of 4-byte integers, native endian.                                }
+     ,xplmType_IntArray                        = 16
+ 
+     { A variable block of data.                                                  }
+     ,xplmType_Data                            = 32
+ 
+   );
+   PXPLMDataTypeID = ^XPLMDataTypeID;
+
+{$IFDEF XPLM400}
+   {
+    XPLMCountDataRefs
+    
+    Returns the total number of datarefs that have been registered in X-Plane.
+   }
+   FUNCTION XPLMCountDataRefs: Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+   {
+    XPLMGetDataRefsByIndex
+    
+    Given an offset and count, this function will return an array of
+    XPLMDataRefs in that range.  The offset/count idiom is useful for things
+    like pagination.
+   }
+   PROCEDURE XPLMGetDataRefsByIndex(
+                                        offset              : Integer;
+                                        count               : Integer;
+                                        outDataRefs         : PXPLMDataRef);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+   {
+    XPLMDataRefInfo_t
+    
+    The XPLMDataRefInfo_t structure contains all of the information about a
+    single data ref.  The structure can be expanded in future SDK APIs to
+    include more features. Always set the structSize member to the size of 
+    your struct in bytes!
+   }
+TYPE
+   XPLMDataRefInfo_t = RECORD
+     { Used to inform XPLMGetDatarefInfo() of the SDK version you compiled        }
+     { against; should always be set to sizeof(XPLMDataRefInfo_t)                 }
+     structSize               : Integer;
+     { The full name/path of the data ref                                         }
+     name                     : XPLMString;
+     type                     : XPLMDataTypeID;
+     { TRUE if the data ref permits writing to it. FALSE if it's read-only.       }
+     writable                 : Integer;
+     { The handle to the plugin that registered this dataref.                     }
+     owner                    : XPLMPluginID;
+   END;
+   PXPLMDataRefInfo_t = ^XPLMDataRefInfo_t;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+   {
+    XPLMGetDataRefInfo
+    
+    Give a data ref, this routine returns a populated struct containing the
+    available information about the dataref.
+   }
+   PROCEDURE XPLMGetDataRefInfo(
+                                        inDataRef           : XPLMDataRef;
+                                        outInfo             : PXPLMDataRefInfo_t);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM400}
+
+   {
+    XPLMFindDataRef
+    
+    Given a C-style string that names the dataref, this routine looks up the
+    actual opaque XPLMDataRef that you use to read and write the data. The
+    string names for datarefs are published on the X-Plane SDK web site.
+    
+    This function returns NULL if the dataref cannot be found.
+    
+    NOTE: this function is relatively expensive; save the XPLMDataRef this
+    function returns for future use. Do not look up your dataref by string
+    every time you need to read or write it.
+   }
+   FUNCTION XPLMFindDataRef(
+                                        inDataRefName       : XPLMString) : XPLMDataRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCanWriteDataRef
+    
+    Given a dataref, this routine returns true if you can successfully set the
+    data, false otherwise. Some datarefs are read-only.
+    
+    NOTE: even if a dataref is marked writable, it may not act writable.  This
+    can happen for datarefs that X-Plane writes to on every frame of
+    simulation.  In some cases, the dataref is writable but you have to set a
+    separate "override" dataref to 1 to stop X-Plane from writing it.
+   }
+   FUNCTION XPLMCanWriteDataRef(
+                                        inDataRef           : XPLMDataRef) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMIsDataRefGood
+    
+    This function returns true if the passed in handle is a valid dataref that
+    is not orphaned.
+    
+    Note: there is normally no need to call this function; datarefs returned by
+    XPLMFindDataRef remain valid (but possibly orphaned) unless there is a
+    complete plugin reload (in which case your plugin is reloaded anyway).
+    Orphaned datarefs can be safely read and return 0. Therefore you never need
+    to call XPLMIsDataRefGood to 'check' the safety of a dataref.
+    (XPLMIsDataRefGood performs some slow checking of the handle validity, so
+    it has a perormance cost.)
+   }
+   FUNCTION XPLMIsDataRefGood(
+                                        inDataRef           : XPLMDataRef) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDataRefTypes
+    
+    This routine returns the types of the dataref for accessor use. If a
+    dataref is available in multiple data types, the bit-wise OR of these types
+    will be returned.
+   }
+   FUNCTION XPLMGetDataRefTypes(
+                                        inDataRef           : XPLMDataRef) : XPLMDataTypeID;
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * DATA ACCESSORS
+ ___________________________________________________________________________}
+{
+   These routines read and write the data references. For each supported data
+   type there is a reader and a writer.
+   
+   If the dataref is orphaned, the plugin that provides it is disabled or
+   there is a type mismatch, the functions that read data will return 0 as a
+   default value or not modify the passed in memory. The plugins that write
+   data will not write under these circumstances or if the dataref is
+   read-only.
+   
+   NOTE: to keep the overhead of reading datarefs low, these routines do not
+   do full validation of a dataref; passing a junk value for a dataref can
+   result in crashing the sim. The get/set APIs do check for NULL.
+   
+   For array-style datarefs, you specify the number of items to read/write and
+   the offset into the array; the actual number of items read or written is
+   returned. This may be less the number requested to prevent an
+   array-out-of-bounds error.
+}
+
+
+   {
+    XPLMGetDatai
+    
+    Read an integer dataref and return its value. The return value is the
+    dataref value or 0 if the dataref is NULL or the plugin is disabled.
+   }
+   FUNCTION XPLMGetDatai(
+                                        inDataRef           : XPLMDataRef) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDatai
+    
+    Write a new value to an integer dataref. This routine is a no-op if the
+    plugin publishing the dataref is disabled, the dataref is NULL, or the
+    dataref is not writable.
+   }
+   PROCEDURE XPLMSetDatai(
+                                        inDataRef           : XPLMDataRef;
+                                        inValue             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDataf
+    
+    Read a single precision floating point dataref and return its value. The
+    return value is the dataref value or 0.0 if the dataref is NULL or the
+    plugin is disabled.
+   }
+   FUNCTION XPLMGetDataf(
+                                        inDataRef           : XPLMDataRef) : Single;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDataf
+    
+    Write a new value to a single precision floating point dataref. This
+    routine is a no-op if the plugin publishing the dataref is disabled, the
+    dataref is NULL, or the dataref is not writable.
+   }
+   PROCEDURE XPLMSetDataf(
+                                        inDataRef           : XPLMDataRef;
+                                        inValue             : Single);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDatad
+    
+    Read a double precision floating point dataref and return its value. The
+    return value is the dataref value or 0.0 if the dataref is NULL or the
+    plugin is disabled.
+   }
+   FUNCTION XPLMGetDatad(
+                                        inDataRef           : XPLMDataRef) : Real;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDatad
+    
+    Write a new value to a double precision floating point dataref. This
+    routine is a no-op if the plugin publishing the dataref is disabled, the
+    dataref is NULL, or the dataref is not writable.
+   }
+   PROCEDURE XPLMSetDatad(
+                                        inDataRef           : XPLMDataRef;
+                                        inValue             : Real);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDatavi
+    
+    Read a part of an integer array dataref. If you pass NULL for outValues,
+    the routine will return the size of the array, ignoring inOffset and inMax.
+    
+    If outValues is not NULL, then up to inMax values are copied from the
+    dataref into outValues, starting at inOffset in the dataref. If inMax +
+    inOffset is larger than the size of the dataref, less than inMax values
+    will be copied. The number of values copied is returned.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   FUNCTION XPLMGetDatavi(
+                                        inDataRef           : XPLMDataRef;
+                                        outValues           : PInteger;    { Can be nil }
+                                        inOffset            : Integer;
+                                        inMax               : Integer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDatavi
+    
+    Write part or all of an integer array dataref. The values passed by
+    inValues are written into the dataref starting at inOffset. Up to inCount
+    values are written; however if the values would write past the end of the
+    dataref array, then fewer values are written.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   PROCEDURE XPLMSetDatavi(
+                                        inDataRef           : XPLMDataRef;
+                                        inValues            : PInteger;
+                                        inoffset            : Integer;
+                                        inCount             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDatavf
+    
+    Read a part of a single precision floating point array dataref. If you pass
+    NULL for outValues, the routine will return the size of the array, ignoring
+    inOffset and inMax.
+    
+    If outValues is not NULL, then up to inMax values are copied from the
+    dataref into outValues, starting at inOffset in the dataref. If inMax +
+    inOffset is larger than the size of the dataref, less than inMax values
+    will be copied. The number of values copied is returned.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   FUNCTION XPLMGetDatavf(
+                                        inDataRef           : XPLMDataRef;
+                                        outValues           : PSingle;    { Can be nil }
+                                        inOffset            : Integer;
+                                        inMax               : Integer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDatavf
+    
+    Write part or all of a single precision floating point array dataref. The
+    values passed by inValues are written into the dataref starting at
+    inOffset. Up to inCount values are written; however if the values would
+    write past the end of the dataref array, then fewer values are written.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   PROCEDURE XPLMSetDatavf(
+                                        inDataRef           : XPLMDataRef;
+                                        inValues            : PSingle;
+                                        inoffset            : Integer;
+                                        inCount             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDatab
+    
+    Read a part of a byte array dataref. If you pass NULL for outValues, the
+    routine will return the size of the array, ignoring inOffset and inMax.
+    
+    If outValues is not NULL, then up to inMax values are copied from the
+    dataref into outValues, starting at inOffset in the dataref. If inMax +
+    inOffset is larger than the size of the dataref, less than inMax values
+    will be copied. The number of values copied is returned.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   FUNCTION XPLMGetDatab(
+                                        inDataRef           : XPLMDataRef;
+                                        outValue            : pointer;    { Can be nil }
+                                        inOffset            : Integer;
+                                        inMaxBytes          : Integer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDatab
+    
+    Write part or all of a byte array dataref. The values passed by inValues
+    are written into the dataref starting at inOffset. Up to inCount values are
+    written; however if the values would write "off the end" of the dataref
+    array, then fewer values are written.
+    
+    Note: the semantics of array datarefs are entirely implemented by the
+    plugin (or X-Plane) that provides the dataref, not the SDK itself; the
+    above description is how these datarefs are intended to work, but a rogue
+    plugin may have different behavior.
+   }
+   PROCEDURE XPLMSetDatab(
+                                        inDataRef           : XPLMDataRef;
+                                        inValue             : pointer;
+                                        inOffset            : Integer;
+                                        inLength            : Integer);
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * PUBLISHING YOUR PLUGIN'S DATA
+ ___________________________________________________________________________}
+{
+   These functions allow you to create data references that other plug-ins and
+   X-Plane can access via the above data access APIs. Data references
+   published by other plugins operate the same as ones published by X-Plane in
+   all manners except that your data reference will not be available to other
+   plugins if/when your plugin is disabled.
+   
+   You share data by registering data provider callback functions. When a
+   plug-in requests your data, these callbacks are then called. You provide
+   one callback to return the value when a plugin 'reads' it and another to
+   change the value when a plugin 'writes' it.
+   
+   Important: you must pick a prefix for your datarefs other than "sim/" -
+   this prefix is reserved for X-Plane. The X-Plane SDK website contains a
+   registry where authors can select a unique first word for dataref names, to
+   prevent dataref collisions between plugins.
+}
+
+
+   {
+    XPLMGetDatai_f
+    
+    Data provider function pointers.
+    
+    These define the function pointers you provide to get or set data. Note
+    that you are passed a generic pointer for each one. This is the same
+    pointer you pass in your register routine; you can use it to locate plugin
+    variables, etc.
+    
+    The semantics of your callbacks are the same as the dataref accessors above
+    - basically routines like XPLMGetDatai are just pass-throughs from a caller
+    to your plugin. Be particularly mindful in implementing array dataref
+    read-write accessors; you are responsible for avoiding overruns, supporting
+    offset read/writes, and handling a read with a NULL buffer.
+   }
+TYPE
+     XPLMGetDatai_f = FUNCTION(
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+   {
+    XPLMSetDatai_f
+   }
+     XPLMSetDatai_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValue             : Integer); cdecl;
+
+   {
+    XPLMGetDataf_f
+   }
+     XPLMGetDataf_f = FUNCTION(
+                                    inRefcon            : pointer) : Single; cdecl;
+
+   {
+    XPLMSetDataf_f
+   }
+     XPLMSetDataf_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValue             : Single); cdecl;
+
+   {
+    XPLMGetDatad_f
+   }
+     XPLMGetDatad_f = FUNCTION(
+                                    inRefcon            : pointer) : Real; cdecl;
+
+   {
+    XPLMSetDatad_f
+   }
+     XPLMSetDatad_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValue             : Real); cdecl;
+
+   {
+    XPLMGetDatavi_f
+   }
+     XPLMGetDatavi_f = FUNCTION(
+                                    inRefcon            : pointer;
+                                    outValues           : PInteger;    { Can be nil }
+                                    inOffset            : Integer;
+                                    inMax               : Integer) : Integer; cdecl;
+
+   {
+    XPLMSetDatavi_f
+   }
+     XPLMSetDatavi_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValues            : PInteger;
+                                    inOffset            : Integer;
+                                    inCount             : Integer); cdecl;
+
+   {
+    XPLMGetDatavf_f
+   }
+     XPLMGetDatavf_f = FUNCTION(
+                                    inRefcon            : pointer;
+                                    outValues           : PSingle;    { Can be nil }
+                                    inOffset            : Integer;
+                                    inMax               : Integer) : Integer; cdecl;
+
+   {
+    XPLMSetDatavf_f
+   }
+     XPLMSetDatavf_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValues            : PSingle;
+                                    inOffset            : Integer;
+                                    inCount             : Integer); cdecl;
+
+   {
+    XPLMGetDatab_f
+   }
+     XPLMGetDatab_f = FUNCTION(
+                                    inRefcon            : pointer;
+                                    outValue            : pointer;    { Can be nil }
+                                    inOffset            : Integer;
+                                    inMaxLength         : Integer) : Integer; cdecl;
+
+   {
+    XPLMSetDatab_f
+   }
+     XPLMSetDatab_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    inValue             : pointer;
+                                    inOffset            : Integer;
+                                    inLength            : Integer); cdecl;
+
+   {
+    XPLMRegisterDataAccessor
+    
+    This routine creates a new item of data that can be read and written. Pass
+    in the data's full name for searching, the type(s) of the data for
+    accessing, and whether the data can be written to. For each data type you
+    support, pass in a read accessor function and a write accessor function if
+    necessary. Pass NULL for data types you do not support or write accessors
+    if you are read-only.
+    
+    You are returned a dataref for the new item of data created. You can use
+    this dataref to unregister your data later or read or write from it.
+   }
+   FUNCTION XPLMRegisterDataAccessor(
+                                        inDataName          : XPLMString;
+                                        inDataType          : XPLMDataTypeID;
+                                        inIsWritable        : Integer;
+                                        inReadInt           : XPLMGetDatai_f;
+                                        inWriteInt          : XPLMSetDatai_f;
+                                        inReadFloat         : XPLMGetDataf_f;
+                                        inWriteFloat        : XPLMSetDataf_f;
+                                        inReadDouble        : XPLMGetDatad_f;
+                                        inWriteDouble       : XPLMSetDatad_f;
+                                        inReadIntArray      : XPLMGetDatavi_f;
+                                        inWriteIntArray     : XPLMSetDatavi_f;
+                                        inReadFloatArray    : XPLMGetDatavf_f;
+                                        inWriteFloatArray   : XPLMSetDatavf_f;
+                                        inReadData          : XPLMGetDatab_f;
+                                        inWriteData         : XPLMSetDatab_f;
+                                        inReadRefcon        : pointer;
+                                        inWriteRefcon       : pointer) : XPLMDataRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterDataAccessor
+    
+    Use this routine to unregister any data accessors you may have registered.
+    You unregister a dataref by the XPLMDataRef you get back from registration.
+    Once you unregister a dataref, your function pointer will not be called
+    anymore.
+   }
+   PROCEDURE XPLMUnregisterDataAccessor(
+                                        inDataRef           : XPLMDataRef);
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * SHARING DATA BETWEEN MULTIPLE PLUGINS
+ ___________________________________________________________________________}
+{
+   The data reference registration APIs from the previous section allow a
+   plugin to publish data in a one-owner manner; the plugin that publishes the
+   data reference owns the real memory that the dataref uses. This is
+   satisfactory for most cases, but there are also cases where plugins need to
+   share actual data.
+   
+   With a shared data reference, no one plugin owns the actual memory for the
+   data reference; the plugin SDK allocates that for you. When the first
+   plugin asks to 'share' the data, the memory is allocated. When the data is
+   changed, every plugin that is sharing the data is notified.
+   
+   Shared data references differ from the 'owned' data references from the
+   previous section in a few ways:
+   
+   * With shared data references, any plugin can create the data reference;
+     with owned plugins one plugin must create the data reference and others
+     subscribe. (This can be a problem if you don't know which set of plugins
+     will be present).
+   
+   * With shared data references, every plugin that is sharing the data is
+     notified when the data is changed. With owned data references, only the
+     one owner is notified when the data is changed.
+   
+   * With shared data references, you cannot access the physical memory of the
+     data reference; you must use the XPLMGet... and XPLMSet... APIs. With an
+     owned data reference, the one owning data reference can manipulate the
+     data reference's memory in any way it sees fit.
+   
+   Shared data references solve two problems: if you need to have a data
+   reference used by several plugins but do not know which plugins will be
+   installed, or if all plugins sharing data need to be notified when that
+   data is changed, use shared data references.
+}
+
+
+   {
+    XPLMDataChanged_f
+    
+    An XPLMDataChanged_f is a callback that the XPLM calls whenever any other
+    plug-in modifies shared data. A refcon you provide is passed back to help
+    identify which data is being changed. In response, you may want to call one
+    of the XPLMGetDataxxx routines to find the new value of the data.
+   }
+TYPE
+     XPLMDataChanged_f = PROCEDURE(
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMShareData
+    
+    This routine connects a plug-in to shared data, creating the shared data if
+    necessary. inDataName is a standard path for the dataref, and inDataType
+    specifies the type. This function will create the data if it does not
+    exist. If the data already exists but the type does not match, an error is
+    returned, so it is important that plug-in authors collaborate to establish
+    public standards for shared data.
+    
+    If a notificationFunc is passed in and is not NULL, that notification
+    function will be called whenever the data is modified. The notification
+    refcon will be passed to it. This allows your plug-in to know which shared
+    data was changed if multiple shared data are handled by one callback, or if
+    the plug-in does not use global variables.
+    
+    A one is returned for successfully creating or finding the shared data; a
+    zero if the data already exists but is of the wrong type.
+   }
+   FUNCTION XPLMShareData(
+                                        inDataName          : XPLMString;
+                                        inDataType          : XPLMDataTypeID;
+                                        inNotificationFunc  : XPLMDataChanged_f;
+                                        inNotificationRefcon: pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnshareData
+    
+    This routine removes your notification function for shared data. Call it
+    when done with the data to stop receiving change notifications. Arguments
+    must match XPLMShareData. The actual memory will not necessarily be freed,
+    since other plug-ins could be using it.
+   }
+   FUNCTION XPLMUnshareData(
+                                        inDataName          : XPLMString;
+                                        inDataType          : XPLMDataTypeID;
+                                        inNotificationFunc  : XPLMDataChanged_f;
+                                        inNotificationRefcon: pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMDefs.pas b/SDK/Delphi/XPLM/XPLMDefs.pas
new file mode 100644
index 0000000..8155f73
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMDefs.pas
@@ -0,0 +1,495 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMDefs;
+INTERFACE
+{
+   This file is contains the cross-platform and basic definitions for the
+   X-Plane SDK.
+   
+   The preprocessor macros APL, LIN and IBM must be defined to specify the
+   compilation target; define APL to 1 to compile on Mac, IBM to 1 to compile
+   on Windows and LIN to 1 to compile on Linux. Only one compilation target
+   may be used at a time. You must specify these macro definitions before
+   including XPLMDefs.h or any other XPLM headers.  You can do this using the
+   -D command line option or a preprocessor header.
+}
+
+   {$A4}
+{$IFDEF LINUX}
+   {$DEFINE KYLIX}
+{$ENDIF}
+TYPE
+{$IFNDEF DELPHI}
+{$IFNDEF KYLIX}
+   Pchar = ^char;
+   Ppchar = ^Pchar;
+   Psingle = ^single;
+   Pinteger = ^integer;
+{$ENDIF}
+{$ENDIF}
+   Preal = ^real;
+   Plongint = ^longint;
+{___________________________________________________________________________
+ * DLL Definitions
+ ___________________________________________________________________________}
+{
+   These definitions control the importing and exporting of functions within
+   the DLL.
+   
+   You can prefix your five required callbacks with the PLUGIN_API macro to
+   declare them as exported C functions.  The XPLM_API macro identifies
+   functions that are provided to you via the plugin SDK.  (Link against
+   XPLM.lib to use these functions.)
+}
+
+
+
+{___________________________________________________________________________
+ * GLOBAL DEFINITIONS
+ ___________________________________________________________________________}
+{
+   These definitions are used in all parts of the SDK.
+}
+
+
+TYPE
+   {
+    XPLMPluginID
+    
+    Each plug-in is identified by a unique integer ID.  This ID can be used to
+    disable or enable a plug-in, or discover what plug-in is 'running' at the
+    time.  A plug-in ID is unique within the currently running instance of
+    X-Plane unless plug-ins are reloaded.  Plug-ins may receive a different
+    unique ID each time they are loaded. This includes the unloading and
+    reloading of plugins that are part of the user's aircraft.
+    
+    For persistent identification of plug-ins, use XPLMFindPluginBySignature in
+    XPLMUtiltiies.h .
+    
+    -1 indicates no plug-in.
+   }
+   XPLMPluginID = Integer;
+   PXPLMPluginID = ^XPLMPluginID;
+
+CONST
+    { No plugin.                                                                 }
+   XPLM_NO_PLUGIN_ID    = (-1);
+
+    { X-Plane itself                                                             }
+   XPLM_PLUGIN_XPLANE   = (0);
+
+    { The current XPLM revision is 4.1.1 (411).                                  }
+   kXPLM_Version        = (411);
+
+   {
+    XPLMKeyFlags
+    
+    These bitfields define modifier keys in a platform independent way. When a
+    key is pressed, a series of messages are sent to your plugin.  The down
+    flag is set in the first of these messages, and the up flag in the last. 
+    While the key is held down, messages are sent with neither flag set to
+    indicate that the key is being held down as a repeated character.
+    
+    The control flag is mapped to the control flag on Macintosh and PC. 
+    Generally X-Plane uses the control key and not the command key on
+    Macintosh, providing a consistent interface across platforms that does not
+    necessarily match the Macintosh user interface guidelines.  There is not
+    yet a way for plugins to access the Macintosh control keys without using
+    #ifdefed code.
+   }
+TYPE
+   XPLMKeyFlags = (
+     { The shift key is down                                                      }
+      xplm_ShiftFlag                           = 1
+ 
+     { The option or alt key is down                                              }
+     ,xplm_OptionAltFlag                       = 2
+ 
+     { The control key is down                                                    }
+     ,xplm_ControlFlag                         = 4
+ 
+     { The key is being pressed down                                              }
+     ,xplm_DownFlag                            = 8
+ 
+     { The key is being released                                                  }
+     ,xplm_UpFlag                              = 16
+ 
+   );
+   PXPLMKeyFlags = ^XPLMKeyFlags;
+
+{___________________________________________________________________________
+ * ASCII CONTROL KEY CODES
+ ___________________________________________________________________________}
+{
+   These definitions define how various control keys are mapped to ASCII key
+   codes. Not all key presses generate an ASCII value, so plugin code should
+   be prepared to see null characters come from the keyboard...this usually
+   represents a key stroke that has no equivalent ASCII, like a page-down
+   press.  Use virtual key codes to find these key strokes.
+   
+   ASCII key codes take into account modifier keys; shift keys will affect
+   capitals and punctuation; control key combinations may have no vaild ASCII
+   and produce NULL.  To detect control-key combinations, use virtual key
+   codes, not ASCII keys.
+}
+
+
+CONST
+   XPLM_KEY_RETURN      = 13;
+
+   XPLM_KEY_ESCAPE      = 27;
+
+   XPLM_KEY_TAB         = 9;
+
+   XPLM_KEY_DELETE      = 8;
+
+   XPLM_KEY_LEFT        = 28;
+
+   XPLM_KEY_RIGHT       = 29;
+
+   XPLM_KEY_UP          = 30;
+
+   XPLM_KEY_DOWN        = 31;
+
+   XPLM_KEY_0           = 48;
+
+   XPLM_KEY_1           = 49;
+
+   XPLM_KEY_2           = 50;
+
+   XPLM_KEY_3           = 51;
+
+   XPLM_KEY_4           = 52;
+
+   XPLM_KEY_5           = 53;
+
+   XPLM_KEY_6           = 54;
+
+   XPLM_KEY_7           = 55;
+
+   XPLM_KEY_8           = 56;
+
+   XPLM_KEY_9           = 57;
+
+   XPLM_KEY_DECIMAL     = 46;
+
+{___________________________________________________________________________
+ * VIRTUAL KEY CODES
+ ___________________________________________________________________________}
+{
+   These are cross-platform defines for every distinct keyboard press on the
+   computer. Every physical key on the keyboard has a virtual key code.  So
+   the "two" key on the top row of the main keyboard has a different code from
+   the "two" key on the numeric key pad.  But the 'w' and 'W' character are
+   indistinguishable by virtual key code because they are the same physical
+   key (one with and one without the shift key).
+   
+   Use virtual key codes to detect keystrokes that do not have ASCII
+   equivalents, allow the user to map the numeric keypad separately from the
+   main keyboard, and detect control key and other modifier-key combinations
+   that generate ASCII control key sequences (many of which are not available
+   directly via character keys in the SDK).
+   
+   To assign virtual key codes we started with the Microsoft set but made some
+   additions and changes.  A few differences:
+   
+   1. Modifier keys are not available as virtual key codes.  You cannot get
+      distinct modifier press and release messages.  Please do not try to use
+      modifier keys as regular keys; doing so will almost certainly interfere
+      with users' abilities to use the native X-Plane key bindings.
+   2. Some keys that do not exist on both Mac and PC keyboards are removed.
+   3. Do not assume that the values of these keystrokes are interchangeable
+      with MS v-keys.
+}
+
+
+CONST
+   XPLM_VK_BACK         = $08;
+
+   XPLM_VK_TAB          = $09;
+
+   XPLM_VK_CLEAR        = $0C;
+
+   XPLM_VK_RETURN       = $0D;
+
+   XPLM_VK_ESCAPE       = $1B;
+
+   XPLM_VK_SPACE        = $20;
+
+   XPLM_VK_PRIOR        = $21;
+
+   XPLM_VK_NEXT         = $22;
+
+   XPLM_VK_END          = $23;
+
+   XPLM_VK_HOME         = $24;
+
+   XPLM_VK_LEFT         = $25;
+
+   XPLM_VK_UP           = $26;
+
+   XPLM_VK_RIGHT        = $27;
+
+   XPLM_VK_DOWN         = $28;
+
+   XPLM_VK_SELECT       = $29;
+
+   XPLM_VK_PRINT        = $2A;
+
+   XPLM_VK_EXECUTE      = $2B;
+
+   XPLM_VK_SNAPSHOT     = $2C;
+
+   XPLM_VK_INSERT       = $2D;
+
+   XPLM_VK_DELETE       = $2E;
+
+   XPLM_VK_HELP         = $2F;
+
+    { XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)  }
+   XPLM_VK_0            = $30;
+
+   XPLM_VK_1            = $31;
+
+   XPLM_VK_2            = $32;
+
+   XPLM_VK_3            = $33;
+
+   XPLM_VK_4            = $34;
+
+   XPLM_VK_5            = $35;
+
+   XPLM_VK_6            = $36;
+
+   XPLM_VK_7            = $37;
+
+   XPLM_VK_8            = $38;
+
+   XPLM_VK_9            = $39;
+
+    { XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)  }
+   XPLM_VK_A            = $41;
+
+   XPLM_VK_B            = $42;
+
+   XPLM_VK_C            = $43;
+
+   XPLM_VK_D            = $44;
+
+   XPLM_VK_E            = $45;
+
+   XPLM_VK_F            = $46;
+
+   XPLM_VK_G            = $47;
+
+   XPLM_VK_H            = $48;
+
+   XPLM_VK_I            = $49;
+
+   XPLM_VK_J            = $4A;
+
+   XPLM_VK_K            = $4B;
+
+   XPLM_VK_L            = $4C;
+
+   XPLM_VK_M            = $4D;
+
+   XPLM_VK_N            = $4E;
+
+   XPLM_VK_O            = $4F;
+
+   XPLM_VK_P            = $50;
+
+   XPLM_VK_Q            = $51;
+
+   XPLM_VK_R            = $52;
+
+   XPLM_VK_S            = $53;
+
+   XPLM_VK_T            = $54;
+
+   XPLM_VK_U            = $55;
+
+   XPLM_VK_V            = $56;
+
+   XPLM_VK_W            = $57;
+
+   XPLM_VK_X            = $58;
+
+   XPLM_VK_Y            = $59;
+
+   XPLM_VK_Z            = $5A;
+
+   XPLM_VK_NUMPAD0      = $60;
+
+   XPLM_VK_NUMPAD1      = $61;
+
+   XPLM_VK_NUMPAD2      = $62;
+
+   XPLM_VK_NUMPAD3      = $63;
+
+   XPLM_VK_NUMPAD4      = $64;
+
+   XPLM_VK_NUMPAD5      = $65;
+
+   XPLM_VK_NUMPAD6      = $66;
+
+   XPLM_VK_NUMPAD7      = $67;
+
+   XPLM_VK_NUMPAD8      = $68;
+
+   XPLM_VK_NUMPAD9      = $69;
+
+   XPLM_VK_MULTIPLY     = $6A;
+
+   XPLM_VK_ADD          = $6B;
+
+   XPLM_VK_SEPARATOR    = $6C;
+
+   XPLM_VK_SUBTRACT     = $6D;
+
+   XPLM_VK_DECIMAL      = $6E;
+
+   XPLM_VK_DIVIDE       = $6F;
+
+   XPLM_VK_F1           = $70;
+
+   XPLM_VK_F2           = $71;
+
+   XPLM_VK_F3           = $72;
+
+   XPLM_VK_F4           = $73;
+
+   XPLM_VK_F5           = $74;
+
+   XPLM_VK_F6           = $75;
+
+   XPLM_VK_F7           = $76;
+
+   XPLM_VK_F8           = $77;
+
+   XPLM_VK_F9           = $78;
+
+   XPLM_VK_F10          = $79;
+
+   XPLM_VK_F11          = $7A;
+
+   XPLM_VK_F12          = $7B;
+
+   XPLM_VK_F13          = $7C;
+
+   XPLM_VK_F14          = $7D;
+
+   XPLM_VK_F15          = $7E;
+
+   XPLM_VK_F16          = $7F;
+
+   XPLM_VK_F17          = $80;
+
+   XPLM_VK_F18          = $81;
+
+   XPLM_VK_F19          = $82;
+
+   XPLM_VK_F20          = $83;
+
+   XPLM_VK_F21          = $84;
+
+   XPLM_VK_F22          = $85;
+
+   XPLM_VK_F23          = $86;
+
+   XPLM_VK_F24          = $87;
+
+    { The following definitions are extended and are not based on the Microsoft  }
+    { key set.                                                                   }
+   XPLM_VK_EQUAL        = $B0;
+
+   XPLM_VK_MINUS        = $B1;
+
+   XPLM_VK_RBRACE       = $B2;
+
+   XPLM_VK_LBRACE       = $B3;
+
+   XPLM_VK_QUOTE        = $B4;
+
+   XPLM_VK_SEMICOLON    = $B5;
+
+   XPLM_VK_BACKSLASH    = $B6;
+
+   XPLM_VK_COMMA        = $B7;
+
+   XPLM_VK_SLASH        = $B8;
+
+   XPLM_VK_PERIOD       = $B9;
+
+   XPLM_VK_BACKQUOTE    = $BA;
+
+   XPLM_VK_ENTER        = $BB;
+
+   XPLM_VK_NUMPAD_ENT   = $BC;
+
+   XPLM_VK_NUMPAD_EQ    = $BD;
+
+   {
+    XPLMFixedString150_t
+    
+    A container for a fixed-size string buffer of 150 characters.
+   }
+TYPE
+   XPLMFixedString150_t = RECORD
+     { The size of the struct.                                                    }
+     buffer[150]              : XPLMChar;
+   END;
+   PXPLMFixedString150_t = ^XPLMFixedString150_t;
+{$IFDEF XPLM200}
+   {
+    XPLMCursorStatus
+    
+    XPLMCursorStatus describes how you would like X-Plane to manage the cursor.
+    See XPLMHandleCursor_f for more info.
+   }
+TYPE
+   XPLMCursorStatus = (
+     { X-Plane manages the cursor normally, plugin does not affect the cusrsor.   }
+      xplm_CursorDefault                       = 0
+ 
+     { X-Plane hides the cursor.                                                  }
+     ,xplm_CursorHidden                        = 1
+ 
+     { X-Plane shows the cursor as the default arrow.                             }
+     ,xplm_CursorArrow                         = 2
+ 
+     { X-Plane shows the cursor but lets you select an OS cursor.                 }
+     ,xplm_CursorCustom                        = 3
+ 
+   );
+   PXPLMCursorStatus = ^XPLMCursorStatus;
+{$ENDIF XPLM200}
+   {
+    XPLMMouseStatus
+    
+        When the mouse is clicked, your mouse click routine is called
+        repeatedly.  It is first called with the mouse down message.  It is
+        then called zero or more times with the mouse-drag message, and finally
+        it is called once with the mouse up message.  All of these messages
+        will be directed to the same window; you are guaranteed to not receive
+        a drag or mouse-up event without first receiving the corresponding
+        mouse-down.
+   }
+TYPE
+   XPLMMouseStatus = (
+      xplm_MouseDown                           = 1
+ 
+     ,xplm_MouseDrag                           = 2
+ 
+     ,xplm_MouseUp                             = 3
+ 
+   );
+   PXPLMMouseStatus = ^XPLMMouseStatus;
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMDisplay.pas b/SDK/Delphi/XPLM/XPLMDisplay.pas
new file mode 100644
index 0000000..da7e2db
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMDisplay.pas
@@ -0,0 +1,2163 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMDisplay;
+INTERFACE
+{
+   This API provides the basic hooks to draw in X-Plane and create user
+   interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in
+   manager takes care of properly setting up the OpenGL context and matrices. 
+   You do not decide when in your code's execution to draw; X-Plane tells you
+   (via callbacks) when it is ready to have your plugin draw.
+   
+   X-Plane's drawing strategy is straightforward: every "frame" the screen is
+   rendered by drawing the 3-D scene (dome, ground, objects, airplanes, etc.)
+   and then drawing the cockpit on top of it.  Alpha blending is used to
+   overlay the cockpit over the world (and the gauges over the panel, etc.).
+   X-Plane user interface elements (including windows like the map, the main
+   menu, etc.) are then drawn on top of the cockpit.
+   
+   There are two ways you can draw: directly and in a window.
+   
+   Direct drawing (deprecated!---more on that below) involves drawing to the
+   screen before or after X-Plane finishes a phase of drawing.  When you draw
+   directly, you can specify whether X-Plane is to complete this phase or not.
+   This allows you to do three things: draw before X-Plane does (under it),
+   draw after X-Plane does (over it), or draw instead of X-Plane.
+   
+   To draw directly, you register a callback and specify which phase you want
+   to intercept.  The plug-in manager will call you over and over to draw that
+   phase.
+   
+   Direct drawing allows you to override scenery, panels, or anything.  Note
+   that you cannot assume that you are the only plug-in drawing at this phase.
+   
+   Direct drawing is deprecated; at some point in the X-Plane 11 run, it will
+   likely become unsupported entirely as X-Plane transitions from OpenGL to
+   modern graphics API backends (e.g., Vulkan, Metal, etc.). In the long term,
+   plugins should use the XPLMInstance API for drawing 3-D objects---this will
+   be much more efficient than general 3-D OpenGL drawing, and it will
+   actually be supported by the new graphics backends. We do not yet know what
+   the post-transition API for generic 3-D drawing will look like (if it
+   exists at all).
+   
+   In contrast to direct drawing, window drawing provides a higher level
+   functionality. With window drawing, you create a 2-D window that takes up a
+   portion of the screen. Window drawing is always two dimensional.  Window
+   drawing is depth controlled; you can specify that you want your window to
+   be brought on top, and other plug-ins may put their window on top of you. 
+   Window drawing also allows you to sign up for key presses and receive mouse
+   clicks.
+   
+   Drawing into the screen of an avionics device, like a GPS or a Primary
+   Flight Display, is a way  to extend or replace X-Plane's avionics. Most
+   screens can be displayed both in a 3d cockpit or 
+   2d panel, and also in separate popup windows. By installing drawing
+    callbacks for a certain avionics  device, you can change or extend the
+    appearance of that device regardless whether it's installed  in a 3d
+    cockpit or used in a separate display for home cockpits because you leave
+    the window managing to X-Plane.
+   
+   There are three ways to get keystrokes:
+   
+   1. If you create a window, the window can take keyboard focus.  It will
+      then receive all keystrokes.  If no window has focus, X-Plane receives
+      keystrokes.  Use this to implement typing in dialog boxes, etc.  Only
+      one window may have focus at a time; your window will be notified if it
+      loses focus.
+   2. If you need low level access to the keystroke stream, install a key
+      sniffer.  Key sniffers can be installed above everything or right in
+      front of the sim.
+   3. If you would like to associate key strokes with commands/functions in
+      your plug-in, you should simply register a command (via
+      XPLMCreateCommand()) and allow users to bind whatever key they choose to
+      that command. Another (now deprecated) method of doing so is to use a
+      hot key---a key-specific callback.  Hotkeys are sent based on virtual
+      key strokes, so any key may be distinctly mapped with any modifiers. 
+      Hot keys can be remapped by other plug-ins.  As a plug-in, you don't
+      have to worry about what your hot key ends up mapped to; other plug-ins
+      may provide a UI for remapping keystrokes.  So hotkeys allow a user to
+      resolve conflicts and customize keystrokes.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * DRAWING CALLBACKS
+ ___________________________________________________________________________}
+{
+   Basic drawing callbacks, for low level intercepting of X-Plane's render
+   loop. The purpose of drawing callbacks is to provide targeted additions or
+   replacements to X-Plane's graphics environment (for example, to add extra
+   custom objects, or replace drawing of the AI aircraft).  Do not assume that
+   the drawing callbacks will be called in the order implied by the
+   enumerations. Also do not assume that each drawing phase ends before
+   another begins; they may be nested.
+   
+   Note that all APIs in this section are deprecated, and will likely be
+   removed during the X-Plane 11 run as part of the transition to
+   Vulkan/Metal/etc. See the XPLMInstance API for future-proof drawing of 3-D
+   objects.
+}
+
+
+   {
+    XPLMDrawingPhase
+    
+    This constant indicates which part of drawing we are in.  Drawing is done
+    from the back to the front.  We get a callback before or after each item.
+    Metaphases provide access to the beginning and end of the 3d (scene) and
+    2d (cockpit) drawing in a manner that is independent of new phases added
+     via X-Plane implementation.
+    
+    **NOTE**: As of XPLM302 the legacy 3D drawing phases (xplm_Phase_FirstScene
+      to xplm_Phase_LastScene) are deprecated. When running under X-Plane 11.50
+      with the modern Vulkan or Metal backend, X-Plane will no longer call
+      these drawing phases. There is a new drawing phase, xplm_Phase_Modern3D,
+      which is supported under OpenGL and Vulkan which is called out roughly
+      where the old before xplm_Phase_Airplanes phase was for blending. This
+      phase is *NOT* supported under Metal and comes with potentially
+      substantial performance overhead. Please do *NOT* opt into this phase if
+      you don't do any actual drawing that requires the depth buffer in some
+      way!
+    
+    **WARNING**: As X-Plane's scenery evolves, some drawing phases may cease to
+      exist and new ones may be invented.  If you need a particularly specific
+      use of these codes, consult Austin and/or be prepared to revise your code
+      as X-Plane evolves.
+   }
+TYPE
+   XPLMDrawingPhase = (
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. This is the earliest point at which you can draw }
+     { in 3-d.                                                                    }
+      xplm_Phase_FirstScene                    = 0
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. Drawing of land and water.                       }
+     ,xplm_Phase_Terrain                       = 5
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. Drawing runways and other airport detail.        }
+     ,xplm_Phase_Airports                      = 10
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. Drawing roads, trails, trains, etc.              }
+     ,xplm_Phase_Vectors                       = 15
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. 3-d objects (houses, smokestacks, etc.           }
+     ,xplm_Phase_Objects                       = 20
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. External views of airplanes, both yours and the  }
+     { AI aircraft.                                                               }
+     ,xplm_Phase_Airplanes                     = 25
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated as of XPLM302. This is the last point at which you can draw in  }
+     { 3-d.                                                                       }
+     ,xplm_Phase_LastScene                     = 30
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM302}
+     { A chance to do modern 3D drawing.                                          }
+     ,xplm_Phase_Modern3D                      = 31
+{$ENDIF XPLM302}
+ 
+     { This is the first phase where you can draw in 2-d.                         }
+     ,xplm_Phase_FirstCockpit                  = 35
+ 
+     { The non-moving parts of the aircraft panel.                                }
+     ,xplm_Phase_Panel                         = 40
+ 
+     { The moving parts of the aircraft panel.                                    }
+     ,xplm_Phase_Gauges                        = 45
+ 
+     { Floating windows from plugins.                                             }
+     ,xplm_Phase_Window                        = 50
+ 
+     { The last chance to draw in 2d.                                             }
+     ,xplm_Phase_LastCockpit                   = 55
+ 
+{$IFDEF XPLM200}
+     { Removed as of XPLM300; Use the full-blown XPLMMap API instead.             }
+     ,xplm_Phase_LocalMap3D                    = 100
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM200}
+     { Removed as of XPLM300; Use the full-blown XPLMMap API instead.             }
+     ,xplm_Phase_LocalMap2D                    = 101
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM200}
+     { Removed as of XPLM300; Use the full-blown XPLMMap API instead.             }
+     ,xplm_Phase_LocalMapProfile               = 102
+{$ENDIF XPLM200}
+ 
+   );
+   PXPLMDrawingPhase = ^XPLMDrawingPhase;
+
+   {
+    XPLMDrawCallback_f
+    
+    This is the prototype for a low level drawing callback.  You are passed in
+    the phase and whether it is before or after.  If you are before the phase,
+    return 1 to let X-Plane draw or 0 to suppress X-Plane drawing.  If you are
+    after the phase the return value is ignored.
+    
+    Refcon is a unique value that you specify when registering the callback,
+    allowing you to slip a pointer to your own data to the callback.
+    
+    Upon entry the OpenGL context will be correctly set up for you and OpenGL
+    will be in 'local' coordinates for 3d drawing and panel coordinates for 2d
+    drawing.  The OpenGL state (texturing, etc.) will be unknown.
+   }
+     XPLMDrawCallback_f = FUNCTION(
+                                    inPhase             : XPLMDrawingPhase;
+                                    inIsBefore          : Integer;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+   {
+    XPLMRegisterDrawCallback
+    
+    This routine registers a low level drawing callback.  Pass in the phase you
+    want to be called for and whether you want to be called before or after. 
+    This routine returns 1 if the registration was successful, or 0 if the
+    phase does not exist in this version of X-Plane.  You may register a
+    callback multiple times for the same or different phases as long as the
+    refcon is unique each time.
+    
+    Note that this function will likely be removed during the X-Plane 11 run as
+    part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for
+    future-proof drawing of 3-D objects.
+   }
+   FUNCTION XPLMRegisterDrawCallback(
+                                        inCallback          : XPLMDrawCallback_f;
+                                        inPhase             : XPLMDrawingPhase;
+                                        inWantsBefore       : Integer;
+                                        inRefcon            : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterDrawCallback
+    
+    This routine unregisters a draw callback.  You must unregister a callback
+    for each time you register a callback if you have registered it multiple
+    times with different refcons.  The routine returns 1 if it can find the
+    callback to unregister, 0 otherwise.
+    
+    Note that this function will likely be removed during the X-Plane 11 run as
+    part of the transition to Vulkan/Metal/etc. See the XPLMInstance API for
+    future-proof drawing of 3-D objects.
+   }
+   FUNCTION XPLMUnregisterDrawCallback(
+                                        inCallback          : XPLMDrawCallback_f;
+                                        inPhase             : XPLMDrawingPhase;
+                                        inWantsBefore       : Integer;
+                                        inRefcon            : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM400}
+{___________________________________________________________________________
+ * AVIONICS API
+ ___________________________________________________________________________}
+{
+   The Avionics API allows you to customize the drawing and behaviour of the
+   built-in cockpit devices (GNS, G1000, etc.), and create your own cockpit
+   devices. For built-in devices, you can draw before and/or after X-Plane
+   does, and optionally prevent X-Plane from drawing the screen at all.
+   Customized built-in devices and custom devices are available in the 3D
+   cockpit as well as in the form of pop-up/pop-out windows.
+   
+   The API also allows you to receive mouse interaction events for your device
+   (click down, drag, and up, mouse wheel scroll, cursor) for both screen and
+   bezel. While these always work when the device is popped-up in its window,
+   you must add a `ATTR_manip_device` manipulator on top of your screen in
+   order to receive mouse events from the 3D cockpit.
+   
+   You can also use the avionics API to control the state and location of
+   cockpit devices' pop-up windows.
+   
+   When working with avionics devices, all co-ordinates you receive when
+   drawing or dealing with click events are in texels. The x-axis grows right,
+   the y-axis grows up. In bezel callbacks, the origin is at the bottom left
+   corner of the bezel. In screen callbacks, the origin is at the bottom-left
+   of the screen. X-Plane takes care of scaling your screen and bezel if the
+   user pops out the device's window: you should always draw your screen and
+   bezel as if they were at the size you specified when registering callbacks
+   or creating a device.
+}
+
+
+   {
+    XPLMDeviceID
+    
+    This constant indicates the device we want to override or enhance. We can
+    get a callback before or after each item.
+   }
+TYPE
+   XPLMDeviceID = (
+     { GNS430, pilot side.                                                        }
+      xplm_device_GNS430_1                     = 0
+ 
+     { GNS430, copilot side.                                                      }
+     ,xplm_device_GNS430_2                     = 1
+ 
+     { GNS530, pilot side.                                                        }
+     ,xplm_device_GNS530_1                     = 2
+ 
+     { GNS530, copilot side.                                                      }
+     ,xplm_device_GNS530_2                     = 3
+ 
+     { generic airliner CDU, pilot side.                                          }
+     ,xplm_device_CDU739_1                     = 4
+ 
+     { generic airliner CDU, copilot side.                                        }
+     ,xplm_device_CDU739_2                     = 5
+ 
+     { G1000 Primary Flight Display, pilot side.                                  }
+     ,xplm_device_G1000_PFD_1                  = 6
+ 
+     { G1000 Multifunction Display.                                               }
+     ,xplm_device_G1000_MFD                    = 7
+ 
+     { G1000 Primary Flight Display, copilot side.                                }
+     ,xplm_device_G1000_PFD_2                  = 8
+ 
+     { Primus CDU, pilot side.                                                    }
+     ,xplm_device_CDU815_1                     = 9
+ 
+     { Primus CDU, copilot side.                                                  }
+     ,xplm_device_CDU815_2                     = 10
+ 
+     { Primus Primary Flight Display, pilot side.                                 }
+     ,xplm_device_Primus_PFD_1                 = 11
+ 
+     { Primus Primary Flight Display, copilot side.                               }
+     ,xplm_device_Primus_PFD_2                 = 12
+ 
+     { Primus Multifunction Display, pilot side.                                  }
+     ,xplm_device_Primus_MFD_1                 = 13
+ 
+     { Primus Multifunction Display, copilot side.                                }
+     ,xplm_device_Primus_MFD_2                 = 14
+ 
+     { Primus Multifunction Display, central.                                     }
+     ,xplm_device_Primus_MFD_3                 = 15
+ 
+     { Primus Radio Management Unit, pilot side.                                  }
+     ,xplm_device_Primus_RMU_1                 = 16
+ 
+     { Primus Radio Management Unit, copilot side.                                }
+     ,xplm_device_Primus_RMU_2                 = 17
+ 
+     { Airbus MCDU, pilot side.                                                   }
+     ,xplm_device_MCDU_1                       = 18
+ 
+     { Airbus MCDU, copilot side.                                                 }
+     ,xplm_device_MCDU_2                       = 19
+ 
+   );
+   PXPLMDeviceID = ^XPLMDeviceID;
+
+   {
+    XPLMAvionicsCallback_f
+    
+    This is the prototype for drawing callbacks for customized built-in device.
+    You are passed in the device you are enhancing/replacing, and (if this is
+    used for a built-in device that you are customizing) whether it is before
+    or after X-Plane drawing. If you are before X-Plane, return 1 to let
+    X-Plane draw or 0 to suppress X-Plane drawing. If you are called after
+    X-Plane, the return value is ignored.
+    
+    Refcon is a unique value that you specify when registering the callback,
+    allowing you to slip a pointer to your own data to the callback.
+    
+    Upon entry the OpenGL context will be correctly set up for you and OpenGL
+    will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+    etc.) will be unknown.
+   }
+     XPLMAvionicsCallback_f = FUNCTION(
+                                    inDeviceID          : XPLMDeviceID;
+                                    inIsBefore          : Integer;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsMouse_f
+    
+    Mouse click callback for clicks into your screen or (2D-popup) bezel,
+    useful if the device you are making simulates a touch-screen the user can
+    click in the 3d cockpit, or if your pop-up's bezel has buttons that the
+    user can click. Return 1 to consume the event, or 0 to let X-Plane process
+    it (for stock avionics devices).
+   }
+TYPE
+     XPLMAvionicsMouse_f = FUNCTION(
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    inMouse             : XPLMMouseStatus;
+                                    inRefcon            : pointer) : Integer; cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsMouseWheel_f
+    
+    Mouse wheel callback for scroll actions into your screen or (2D-popup)
+    bezel, useful if your bezel has knobs that can be turned using the mouse
+    wheel, or if you want to simulate pinch-to-zoom on a touchscreen. Return 1
+    to consume the event, or 0 to let X-Plane process it (for stock avionics
+    devices). The number of "clicks" indicates how far the wheel was turned
+    since the last callback. The wheel is 0 for the vertical axis or 1 for the
+    horizontal axis (for OS/mouse combinations that support this).
+   }
+     XPLMAvionicsMouseWheel_f = FUNCTION(
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    wheel               : Integer;
+                                    clicks              : Integer;
+                                    inRefcon            : pointer) : Integer; cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsCursor_f
+    
+    Cursor callback that decides which cursor to show when the mouse is over
+    your screen or (2D-popup) bezel. Return xplm_CursorDefault to let X-Plane
+    use which cursor to show, or other values to force the cursor to a
+    particular one (see XPLMCursorStatus).
+   }
+     XPLMAvionicsCursor_f = FUNCTION(
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    inRefcon            : pointer) : XPLMCursorStatus; cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsKeyboard_f
+    
+    Key callback called when your device is popped up and you've requested to
+    capture the keyboard.  Return 1 to consume the event, or 0 to let X-Plane
+    process it (for stock avionics devices).
+   }
+     XPLMAvionicsKeyboard_f = FUNCTION(
+                                    inKey               : XPLMChar;
+                                    inFlags             : XPLMKeyFlags;
+                                    inVirtualKey        : XPLMChar;
+                                    inRefCon            : pointer;
+                                    losingFocus         : Integer) : Integer; cdecl;
+{$ENDIF XPLM410}
+
+TYPE
+   {
+    XPLMAvionicsID
+    
+    This is an opaque identifier for an avionics display that you enhance or
+    replace.  When you register your callbacks (via
+    XPLMRegisterAvionicsCallbacksEx()) or create a new device (via
+    XPLMCreateAvionicsDevice()), you will specify drawing and mouse callbacks,
+    and get back such a handle.
+   }
+   XPLMAvionicsID = pointer;
+   PXPLMAvionicsID = ^XPLMAvionicsID;
+
+   {
+    XPLMCustomizeAvionics_t
+    
+    The XPLMCustomizeAvionics_t structure defines all of the parameters used to
+    replace or  enhance built-in simulator avionics devices using
+    XPLMRegisterAvionicsCallbacksEx(). The structure will be expanded in future
+    SDK APIs to include more features. Always set the structSize member to the
+    size of your struct in bytes!
+   }
+   XPLMCustomizeAvionics_t = RECORD
+     { Used to inform XPLMRegisterAvionicsCallbacksEx() of the SDK version you    }
+     { compiled against; should always be set to sizeof(XPLMCustomizeAvionics_t)  }
+     structSize               : Integer;
+     { The built-in avionics device to which you want your drawing applied.       }
+     deviceId                 : XPLMDeviceID;
+     { The draw callback to be called before X-Plane draws.                       }
+     drawCallbackBefore       : XPLMAvionicsCallback_f;
+     { The draw callback to be called after X-Plane has drawn.                    }
+     drawCallbackAfter        : XPLMAvionicsCallback_f;
+{$IFDEF XPLM410}
+     { The mouse click callback that is called when the user clicks onto the      }
+     { device's bezel.                                                            }
+     bezelClickCallback       : XPLMAvionicsMouse_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The mouse click callback that is called when the user clicks onto the      }
+     { device's bezel.                                                            }
+     bezelRightClickCallback  : XPLMAvionicsMouse_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The callback that is called when the users uses the scroll wheel over the  }
+     { device's bezel.                                                            }
+     bezelScrollCallback      : XPLMAvionicsMouseWheel_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The callback that lets you determine what cursor should be shown when the  }
+     { mouse is over the device's bezel.                                          }
+     bezelCursorCallback      : XPLMAvionicsCursor_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The mouse click callback that is called when the user clicks onto the      }
+     { device's screen.                                                           }
+     screenTouchCallback      : XPLMAvionicsMouse_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The right mouse click callback that is called when the user clicks onto the}
+     { device's screen.                                                           }
+     screenRightTouchCallback : XPLMAvionicsMouse_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The callback that is called when the users uses the scroll wheel over the  }
+     { device's screen.                                                           }
+     screenScrollCallback     : XPLMAvionicsMouseWheel_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The callback that lets you determine what cursor should be shown when the  }
+     { mouse is over the device's screen.                                         }
+     screenCursorCallback     : XPLMAvionicsCursor_f;
+{$ENDIF XPLM410}
+{$IFDEF XPLM410}
+     { The key callback that is called when the user types in the device's popup. }
+     keyboardCallback         : XPLMAvionicsKeyboard_f;
+{$ENDIF XPLM410}
+     { A reference which will be passed into each of your draw callbacks. Use this}
+     { to pass information to yourself as needed.                                 }
+     refcon                   : pointer;
+   END;
+   PXPLMCustomizeAvionics_t = ^XPLMCustomizeAvionics_t;
+
+   {
+    XPLMRegisterAvionicsCallbacksEx
+    
+    This routine registers your callbacks for a built-in device. This returns a
+    handle. If the returned handle is NULL, there was a problem interpreting
+    your input, most likely the struct size was wrong for your SDK version. If
+    the returned handle is not NULL, your callbacks will be called according to
+    schedule as long as your plugin is not deactivated, or unloaded, or you
+    call XPLMUnregisterAvionicsCallbacks().
+    
+    Note that you cannot register new callbacks for a device that is not a
+    built-in one (for example a device that you have created, or a device
+    another plugin has created).
+   }
+   FUNCTION XPLMRegisterAvionicsCallbacksEx(
+                                        inParams            : PXPLMCustomizeAvionics_t) : XPLMAvionicsID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetAvionicsHandle
+    
+    This routine registers no callbacks for a built-in cockpit device, but
+    returns a handle which allows you to interact with it using the Avionics
+    Device API. Use this if you do not wish to intercept drawing, clicks and
+    touchscreen calls to a device, but want to interact with its popup
+    programmatically. This is equivalent to calling
+    XPLMRegisterAvionicsCallbackEx() with NULL for all callbacks.
+   }
+   FUNCTION XPLMGetAvionicsHandle(
+                                        inDeviceID          : XPLMDeviceID) : XPLMAvionicsID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterAvionicsCallbacks
+    
+    This routine unregisters your callbacks for a built-in device. You should
+    only call this for handles you acquired from
+    XPLMRegisterAvionicsCallbacksEx(). They will no longer be called.
+   }
+   PROCEDURE XPLMUnregisterAvionicsCallbacks(
+                                        inAvionicsId        : XPLMAvionicsID);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsScreenCallback_f
+    
+    This is the prototype for drawing callbacks for custom devices' screens.
+    Refcon is a unique value that you specify when creating the device,
+    allowing you to slip a pointer to your own data to the callback.
+    
+    Upon entry the OpenGL context will be correctly set up for you and OpenGL
+    will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+    etc.) will be unknown. X-Plane does not clear your screen for you between
+    calls - this means you can re-use portions to save drawing, but otherwise
+    you must call glClear() to erase the screen's contents.
+   }
+TYPE
+     XPLMAvionicsScreenCallback_f = PROCEDURE(
+                                    inRefcon            : pointer); cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsBezelCallback_f
+    
+    This is the prototype for drawing callbacks for custom devices' bezel. You
+    are passed in the red, green, and blue values you can optinally use for
+    tinting your bezel accoring to ambiant light.
+    
+    Refcon is a unique value that you specify when creating the device,
+    allowing you to slip a pointer to your own data to the callback.
+    
+    Upon entry the OpenGL context will be correctly set up for you and OpenGL
+    will be in panel coordinates for 2d drawing.  The OpenGL state (texturing,
+    etc.) will be unknown.
+   }
+     XPLMAvionicsBezelCallback_f = PROCEDURE(
+                                    inAmbiantR          : Single;
+                                    inAmbiantG          : Single;
+                                    inAmbiantB          : Single;
+                                    inRefcon            : pointer); cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsBrightness_f
+    
+    This is the prototype for screen brightness callbacks for custom devices.
+    If you provide a callback, you can return the ratio of the screen's maximum
+    brightness that the simulator should use when displaying the screen in the
+    3D cockpit.
+    
+    inRheoValue is the current ratio value (between 0 and 1) of the instrument
+    brightness rheostat to which the device is bound.
+    
+    inAmbientBrightness is the value (between 0 and 1) that the callback should
+    return for the screen to be at a usable brightness based on ambient light
+    (if your device has a photo cell and automatically adjusts its brightness,
+    you can return this and your screen will be at the optimal brightness to be
+    readable, but not blind the pilot).
+    
+    inBusVoltsRatio is the ratio of the nominal voltage currently present on
+    the bus to which the device is bound, or -1 if the device is not bound to
+    the current aircraft.
+    
+    Refcon is a unique value that you specify when creating the device,
+    allowing you to slip a pointer to your own data to the callback.
+   }
+     XPLMAvionicsBrightness_f = FUNCTION(
+                                    inRheoValue         : Single;
+                                    inAmbiantBrightness : Single;
+                                    inBusVoltsRatio     : Single;
+                                    inRefcon            : pointer) : Single; cdecl;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMCreateAvionics_t
+    
+    The XPLMCreateAvionics_t structure defines all of the parameters used to
+    generate your own glass cockpit device by using XPLMCreateAvionicsEx(). The
+    structure will be expanded in future SDK APIs to include more features.
+    Always set the structSize member to the size of your struct in bytes!
+   }
+   XPLMCreateAvionics_t = RECORD
+     { Used to inform XPLMCreateAvionicsEx() of the SDK version you compiled      }
+     { against; should always be set to sizeof(XPLMCreateAvionics_t)              }
+     structSize               : Integer;
+     { Width of the device's screen in pixels.                                    }
+     screenWidth              : Integer;
+     { Height of the device's screen in pixels.                                   }
+     screenHeight             : Integer;
+     { Width of the bezel around your device's screen for 2D pop-ups.             }
+     bezelWidth               : Integer;
+     { Height of the bezel around your device's screen for 2D pop-ups.            }
+     bezelHeight              : Integer;
+     { The screen's lateral offset into the bezel for 2D pop-ups.                 }
+     screenOffsetX            : Integer;
+     { The screen's vertical offset into the bezel for 2D pop-ups.                }
+     screenOffsetY            : Integer;
+     { If set to true (1), X-Plane won't call your plugin to re-render the        }
+     { device's screen every frame. Instead, you should tell X-Plane you want to  }
+     { refresh your screen with XPLMAvionicsNeedsDrawing(), and X-Plane will call }
+     { you before rendering the next simulator frame.                             }
+     drawOnDemand             : Integer;
+     { The draw callback you will use to draw the 2D-popup bezel. This is called  }
+     { only when the popup window is visible, and X-Plane is about to draw the    }
+     { bezel in it.                                                               }
+     bezelDrawCallback        : XPLMAvionicsBezelCallback_f;
+     { The draw callback you will be using to draw into the device's screen       }
+     { framebuffer.                                                               }
+     drawCallback             : XPLMAvionicsScreenCallback_f;
+     { The mouse click callback that is called when the user clicks onto your     }
+     { bezel.                                                                     }
+     bezelClickCallback       : XPLMAvionicsMouse_f;
+     { The mouse click callback that is called when the user clicks onto your     }
+     { bezel.                                                                     }
+     bezelRightClickCallback  : XPLMAvionicsMouse_f;
+     { The callback that is called when the users uses the scroll wheel over your }
+     { avionics' bezel.                                                           }
+     bezelScrollCallback      : XPLMAvionicsMouseWheel_f;
+     { The callback that lets you determine what cursor should be shown when the  }
+     { mouse is over your device's bezel.                                         }
+     bezelCursorCallback      : XPLMAvionicsCursor_f;
+     { The mouse click callback that is called when the user clicks onto your     }
+     { screen.                                                                    }
+     screenTouchCallback      : XPLMAvionicsMouse_f;
+     { The right mouse click callback that is called when the user clicks onto    }
+     { your screen.                                                               }
+     screenRightTouchCallback : XPLMAvionicsMouse_f;
+     { The callback that is called when the users uses the scroll wheel over your }
+     { avionics' screen.                                                          }
+     screenScrollCallback     : XPLMAvionicsMouseWheel_f;
+     { The callback that lets you determine what cursor should be shown when the  }
+     { mouse is over your device's screen.                                        }
+     screenCursorCallback     : XPLMAvionicsCursor_f;
+     { The key callback that is called when the user types in your popup.         }
+     keyboardCallback         : XPLMAvionicsKeyboard_f;
+     { The callback that is called to determine the absolute brightness of the    }
+     { device's screen. Set to NULL to use X-Plane's default behaviour.           }
+     brightnessCallback       : XPLMAvionicsBrightness_f;
+     { A null-terminated string of maximum 64 characters to uniquely identify your}
+     { cockpit device. This must be unique (you cannot re-use an ID that X-Plane  }
+     { or another plugin provides), and it must not contain spaces. This is the   }
+     { string the OBJ file must reference when marking polygons with              }
+     { ATTR_cockpit_device. The string is copied when you call                    }
+     { XPLMCreateAvionicsEx, so you don't need to hold this string in memory after}
+     { the call.                                                                  }
+     deviceID                 : XPLMString;
+     { A null-terminated string to give a user-readable name to your device, which}
+     { can be presented in UI dialogs.                                            }
+     deviceName               : XPLMString;
+     { A reference which will be passed into your draw and mouse callbacks. Use   }
+     { this to pass information to yourself as needed.                            }
+     refcon                   : pointer;
+   END;
+   PXPLMCreateAvionics_t = ^XPLMCreateAvionics_t;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMCreateAvionicsEx
+    
+    Creates a new cockpit device to be used in the 3D cockpit. You can call
+    this at any time: if an aircraft referencing your device is loaded before
+    your plugin, the simulator will make sure to retroactively map your display
+    into it.
+    
+                When you are done with the device, and at least before your
+                plugin is unloaded, you should destroy the device using
+                XPLMDestroyAvionics().
+   }
+   FUNCTION XPLMCreateAvionicsEx(
+                                        inParams            : PXPLMCreateAvionics_t) : XPLMAvionicsID;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMDestroyAvionics
+    
+    Destroys the cockpit device and deallocates its screen's memory. You should
+    only ever call this for devices that you created using
+    XPLMCreateAvionicsEx(), not X-Plane' built-ine devices you have customised.
+   }
+   PROCEDURE XPLMDestroyAvionics(
+                                        inHandle            : XPLMAvionicsID);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMIsAvionicsBound
+    
+    Returns true (1) if the cockpit device with the given handle is used by the
+    current aircraft.
+   }
+   FUNCTION XPLMIsAvionicsBound(
+                                        inHandle            : XPLMAvionicsID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetAvionicsBrightnessRheo
+    
+    Sets the brightness setting's value, between 0 and 1, for the screen of the
+    cockpit device with the given handle.
+    
+    If the device is bound to the current aircraft, this is a shortcut to
+    setting the brightness rheostat value using the
+    `sim/cockpit2/switches/instrument_brightness_ratio[]` dataref; this sets
+    the slot in the `instrument_brightness_ratio` array to which the device is
+    bound.
+    
+    If the device is not currently bound, the device keeps track of its own
+    screen brightness rheostat, allowing you to control the brightness even
+    though it isn't connected to the `instrument_brightness_ratio` dataref.
+   }
+   PROCEDURE XPLMSetAvionicsBrightnessRheo(
+                                        inHandle            : XPLMAvionicsID;
+                                        brightness          : Single);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetAvionicsBrightnessRheo
+    
+    Returns the brightness setting value, between 0 and 1, for the screen of
+    the cockpit device with the given handle.
+    
+            If the device is bound to the current aircraft, this is a shortcut
+            to getting the brightness rheostat value from the
+            `sim/cockpit2/switches/instrument_brightness_ratio[]` dataref; this
+            gets the slot in the `instrument_brightness_ratio` array to which
+            the device is bound.
+    
+            If the device is not currently bound, this returns the device's own
+            brightness rheostat value.
+   }
+   FUNCTION XPLMGetAvionicsBrightnessRheo(
+                                        inHandle            : XPLMAvionicsID) : Single;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetAvionicsBusVoltsRatio
+    
+    Returns the ratio of the nominal voltage (1.0 means full nominal voltage)
+    of the electrical bus to which the given avionics device is bound, or -1 if
+    the device is not bound to the current aircraft.
+   }
+   FUNCTION XPLMGetAvionicsBusVoltsRatio(
+                                        inHandle            : XPLMAvionicsID) : Single;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMIsCursorOverAvionics
+    
+    Returns true (1) if the mouse is currently over the screen of cockpit
+    device with the given handle. If they are not NULL, the optional x and y
+    arguments are filled with the co-ordinates of the mouse cursor in device
+    co-ordinates.
+   }
+   FUNCTION XPLMIsCursorOverAvionics(
+                                        inHandle            : XPLMAvionicsID;
+                                        outX                : PInteger;    { Can be nil }
+                                        outY                : PInteger) : Integer;    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMAvionicsNeedsDrawing
+    
+    Tells X-Plane that your device's screen needs to be re-drawn. If your
+    device is marked for on-demand drawing, X-Plane will call your screen
+    drawing callback before drawing the next simulator frame. If your device is
+    already drawn every frame, this has no effect.
+   }
+   PROCEDURE XPLMAvionicsNeedsDrawing(
+                                        inHandle            : XPLMAvionicsID);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetAvionicsPopupVisible
+    
+    Shows or hides the popup window for a cockpit device.
+   }
+   PROCEDURE XPLMSetAvionicsPopupVisible(
+                                        inHandle            : XPLMAvionicsID;
+                                        inVisible           : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMIsAvionicsPopupVisible
+    
+    Returns true (1) if the popup window for a cockpit device is visible.
+   }
+   FUNCTION XPLMIsAvionicsPopupVisible(
+                                        inHandle            : XPLMAvionicsID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMPopOutAvionics
+    
+    Pops out the window for a cockpit device.
+   }
+   PROCEDURE XPLMPopOutAvionics(
+                                        inHandle            : XPLMAvionicsID);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMIsAvionicsPoppedOut
+    
+    Returns true (1) if the popup window for a cockpit device is popped out.
+   }
+   FUNCTION XPLMIsAvionicsPoppedOut(
+                                        inHandle            : XPLMAvionicsID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMTakeAvionicsKeyboardFocus
+    
+    This routine gives keyboard focus to the popup window of a custom cockpit
+    device, if it is visible.
+   }
+   PROCEDURE XPLMTakeAvionicsKeyboardFocus(
+                                        inHandle            : XPLMAvionicsID);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMHasAvionicsKeyboardFocus
+    
+    Returns true (1) if the popup window for a cockpit device has keyboard
+    focus.
+   }
+   FUNCTION XPLMHasAvionicsKeyboardFocus(
+                                        inHandle            : XPLMAvionicsID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetAvionicsGeometry
+    
+    Returns the bounds of a cockpit device's popup window in the X-Plane
+    coordinate system.
+   }
+   PROCEDURE XPLMGetAvionicsGeometry(
+                                        inHandle            : XPLMAvionicsID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetAvionicsGeometry
+    
+    Sets the size and position of a cockpit device's popup window in the
+    X-Plane coordinate system.
+   }
+   PROCEDURE XPLMSetAvionicsGeometry(
+                                        inHandle            : XPLMAvionicsID;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetAvionicsGeometryOS
+    
+    Returns the bounds of a cockpit device's popped-out window.
+   }
+   PROCEDURE XPLMGetAvionicsGeometryOS(
+                                        inHandle            : XPLMAvionicsID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetAvionicsGeometryOS
+    
+    Sets the size and position of a cockpit device's popped-out window.
+   }
+   PROCEDURE XPLMSetAvionicsGeometryOS(
+                                        inHandle            : XPLMAvionicsID;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$ENDIF XPLM400}
+{___________________________________________________________________________
+ * WINDOW API
+ ___________________________________________________________________________}
+{
+   The window API provides a high-level abstraction for drawing with UI
+   interaction.
+   
+   Windows may operate in one of two modes: legacy (for plugins compiled
+   against old versions of the XPLM, as well as windows created via the
+   deprecated XPLMCreateWindow() function, rather than XPLMCreateWindowEx()),
+   or modern (for windows compiled against the XPLM300 or newer API, and
+   created via XPLMCreateWindowEx()).
+   
+   Modern windows have access to new X-Plane 11 windowing features, like
+   support for new positioning modes (including being "popped out" into their
+   own first-class window in the operating system). They can also optionally
+   be decorated in the style of X-Plane 11 windows (like the map).
+   
+   Modern windows operate in "boxel" units. A boxel ("box of pixels") is a
+   unit of virtual pixels which, depending on X-Plane's scaling, may
+   correspond to an arbitrary NxN "box" of real pixels on screen. Because
+   X-Plane handles this scaling automatically, you can effectively treat the
+   units as though you were simply drawing in pixels, and know that when
+   X-Plane is running with 150% or 200% scaling, your drawing will be
+   automatically scaled (and likewise all mouse coordinates, screen bounds,
+   etc. will also be auto-scaled).
+   
+   In contrast, legacy windows draw in true screen pixels, and thus tend to
+   look quite small when X-Plane is operating in a scaled mode.
+   
+   Legacy windows have their origin in the lower left of the main X-Plane
+   window. In contrast, since modern windows are not constrained to the main
+   window, they have their origin in the lower left of the entire global
+   desktop space, and the lower left of the main X-Plane window is not
+   guaranteed to be (0, 0). In both cases, x increases as you move left, and y
+   increases as you move up.
+}
+
+
+TYPE
+   {
+    XPLMWindowID
+    
+    This is an opaque identifier for a window.  You use it to control your
+    window. When you create a window (via either XPLMCreateWindow() or
+    XPLMCreateWindowEx()), you will specify callbacks to handle drawing, mouse
+    interaction, etc.
+   }
+   XPLMWindowID = pointer;
+   PXPLMWindowID = ^XPLMWindowID;
+
+   {
+    XPLMDrawWindow_f
+    
+    A callback to handle 2-D drawing of your window.  You are passed in your
+    window and its refcon. Draw the window.  You can use other XPLM functions
+    from this header to find the current dimensions of your window, etc.  When
+    this callback is called, the OpenGL context will be set properly for 2-D
+    window drawing.
+    
+    **Note**: Because you are drawing your window over a background, you can
+      make a translucent window easily by simply not filling in your entire
+      window's bounds.
+   }
+     XPLMDrawWindow_f = PROCEDURE(
+                                    inWindowID          : XPLMWindowID;
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMHandleKey_f
+    
+    This function is called when a key is pressed or keyboard focus is taken
+    away from your window.  If losingFocus is 1, you are losing the keyboard
+    focus, otherwise a key was pressed and inKey contains its character.
+    
+    The window ID passed in will be your window for key presses, or the other
+    window taking focus  when losing focus. Note that in the modern plugin
+    system, often focus is taken by the window manager itself; for this resaon,
+    the window ID may be zero when losing focus, and you should not write code
+    that depends onit.
+    
+    The refcon passed in will be the one from registration, for both key
+    presses and losing focus.  
+    
+    Warning: this API declares virtual keys as a signed character; however the
+    VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values
+    (that is 0x80 instead of -0x80).  So you may need to cast the incoming vkey
+    to an unsigned char to get correct comparisons in C.
+   }
+     XPLMHandleKey_f = PROCEDURE(
+                                    inWindowID          : XPLMWindowID;
+                                    inKey               : XPLMChar;
+                                    inFlags             : XPLMKeyFlags;
+                                    inVirtualKey        : XPLMChar;
+                                    inRefcon            : pointer;
+                                    losingFocus         : Integer); cdecl;
+
+   {
+    XPLMHandleMouseClick_f
+    
+    You receive this call for one of three events:
+    
+    - when the user clicks the mouse button down
+    - (optionally) when the user drags the mouse after a down-click, but before
+      the up-click
+    - when the user releases the down-clicked mouse button.
+    
+    You receive the x and y of the click, your window, and a refcon.  Return 1
+    to consume the click, or 0 to pass it through.
+    
+    WARNING: passing clicks through windows (as of this writing) causes mouse
+    tracking problems in X-Plane; do not use this feature!
+    
+    The units for x and y values match the units used in your window. Thus, for
+    "modern" windows (those created via XPLMCreateWindowEx() and compiled
+    against the XPLM300 library), the units are boxels, while legacy windows
+    will get pixels. Legacy windows have their origin in the lower left of the
+    main X-Plane window, while modern windows have their origin in the lower
+    left of the global desktop space. In both cases, x increases as you move
+    right, and y increases as you move up.
+   }
+     XPLMHandleMouseClick_f = FUNCTION(
+                                    inWindowID          : XPLMWindowID;
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    inMouse             : XPLMMouseStatus;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+{$IFDEF XPLM200}
+   {
+    XPLMHandleCursor_f
+    
+    The SDK calls your cursor status callback when the mouse is over your
+    plugin window.  Return a cursor status code to indicate how you would like
+    X-Plane to manage the cursor.  If you return xplm_CursorDefault, the SDK
+    will try lower-Z-order plugin windows, then let the sim manage the cursor.
+    
+    Note: you should never show or hide the cursor yourself---these APIs are
+    typically reference-counted and thus cannot safely and predictably be used
+    by the SDK.  Instead return one of xplm_CursorHidden to hide the cursor or
+    xplm_CursorArrow/xplm_CursorCustom to show the cursor.
+    
+    If you want to implement a custom cursor by drawing a cursor in OpenGL, use
+    xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d
+    drawing callback (after xplm_Phase_Window is probably a good choice, but
+    see deprecation warnings on the drawing APIs!).  If you want to use a
+    custom OS-based cursor, use xplm_CursorCustom to ask X-Plane to show the
+    cursor but not affect its image.  You can then use an OS specific call like
+    SetThemeCursor (Mac) or SetCursor/LoadCursor (Windows).
+    
+    The units for x and y values match the units used in your window. Thus, for
+    "modern" windows (those created via XPLMCreateWindowEx() and compiled
+    against the XPLM300 library), the units are boxels, while legacy windows
+    will get pixels. Legacy windows have their origin in the lower left of the
+    main X-Plane window, while modern windows have their origin in the lower
+    left of the global desktop space. In both cases, x increases as you move
+    right, and y increases as you move up.
+   }
+TYPE
+     XPLMHandleCursor_f = FUNCTION(
+                                    inWindowID          : XPLMWindowID;
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    inRefcon            : pointer) : XPLMCursorStatus; cdecl;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+   {
+    XPLMHandleMouseWheel_f
+    
+    The SDK calls your mouse wheel callback when one of the mouse wheels is
+    scrolled within your window.  Return 1 to consume the mouse wheel movement
+    or 0 to pass them on to a lower window.  (If your window appears opaque to
+    the user, you should consume mouse wheel scrolling even if it does
+    nothing.)  The number of "clicks" indicates how far the wheel was turned
+    since the last callback. The wheel is 0 for the vertical axis or 1 for the
+    horizontal axis (for OS/mouse combinations that support this).
+    
+    The units for x and y values match the units used in your window. Thus, for
+    "modern" windows (those created via XPLMCreateWindowEx() and compiled
+    against the XPLM300 library), the units are boxels, while legacy windows
+    will get pixels. Legacy windows have their origin in the lower left of the
+    main X-Plane window, while modern windows have their origin in the lower
+    left of the global desktop space. In both cases, x increases as you move
+    right, and y increases as you move up.
+   }
+     XPLMHandleMouseWheel_f = FUNCTION(
+                                    inWindowID          : XPLMWindowID;
+                                    x                   : Integer;
+                                    y                   : Integer;
+                                    wheel               : Integer;
+                                    clicks              : Integer;
+                                    inRefcon            : pointer) : Integer; cdecl;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM300}
+   {
+    XPLMWindowLayer
+    
+    XPLMWindowLayer describes where in the ordering of windows X-Plane should
+    place a particular window. Windows in higher layers cover windows in lower
+    layers. So, a given window might be at the top of its particular layer, but
+    it might still be obscured by a window in a higher layer. (This happens
+    frequently when floating windows, like X-Plane's map, are covered by a
+    modal alert.)
+    
+    Your window's layer can only be specified when you create the window (in
+    the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()). For this reason,
+    layering only applies to windows created with new X-Plane 11 GUI features.
+    (Windows created using the older XPLMCreateWindow(), or windows compiled
+    against a pre-XPLM300 version of the SDK will simply be placed in the
+    flight overlay window layer.)
+   }
+TYPE
+   XPLMWindowLayer = (
+     { The lowest layer, used for HUD-like displays while flying.                 }
+      xplm_WindowLayerFlightOverlay            = 0
+ 
+     { Windows that "float" over the sim, like the X-Plane 11 map does. If you are}
+     { not sure which layer to create your window in, choose floating.            }
+     ,xplm_WindowLayerFloatingWindows          = 1
+ 
+     { An interruptive modal that covers the sim with a transparent black overlay }
+     { to draw the user's focus to the alert                                      }
+     ,xplm_WindowLayerModal                    = 2
+ 
+     { "Growl"-style notifications that are visible in a corner of the screen,    }
+     { even over modals                                                           }
+     ,xplm_WindowLayerGrowlNotifications       = 3
+ 
+   );
+   PXPLMWindowLayer = ^XPLMWindowLayer;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM301}
+   {
+    XPLMWindowDecoration
+    
+    XPLMWindowDecoration describes how "modern" windows will be displayed. This
+    impacts both how X-Plane draws your window as well as certain mouse
+    handlers.
+    
+    Your window's decoration can only be specified when you create the window
+    (in the XPLMCreateWindow_t you pass to XPLMCreateWindowEx()).
+   }
+TYPE
+   XPLMWindowDecoration = (
+     { X-Plane will draw no decoration for your window, and apply no automatic    }
+     { click handlers. The window will not stop click from passing through its    }
+     { bounds. This is suitable for "windows" which request, say, the full screen }
+     { bounds, then only draw in a small portion of the available area.           }
+      xplm_WindowDecorationNone                = 0
+ 
+     { The default decoration for "native" windows, like the map. Provides a solid}
+     { background, as well as click handlers for resizing and dragging the window.}
+     ,xplm_WindowDecorationRoundRectangle      = 1
+ 
+     { X-Plane will draw no decoration for your window, nor will it provide resize}
+     { handlers for your window edges, but it will stop clicks from passing       }
+     { through your windows bounds.                                               }
+     ,xplm_WindowDecorationSelfDecorated       = 2
+ 
+     { Like self-decorated, but with resizing; X-Plane will draw no decoration for}
+     { your window, but it will stop clicks from passing through your windows     }
+     { bounds, and provide automatic mouse handlers for resizing.                 }
+     ,xplm_WindowDecorationSelfDecoratedResizable = 3
+ 
+   );
+   PXPLMWindowDecoration = ^XPLMWindowDecoration;
+{$ENDIF XPLM301}
+
+{$IFDEF XPLM200}
+   {
+    XPLMCreateWindow_t
+    
+    The XPMCreateWindow_t structure defines all of the parameters used to
+    create a modern window using XPLMCreateWindowEx().  The structure will be
+    expanded in future SDK APIs to include more features.  Always set the
+    structSize member to the size of your struct in bytes!
+    
+    All windows created by this function in the XPLM300 version of the API are
+    created with the new X-Plane 11 GUI features. This means your plugin will
+    get to "know" about the existence of X-Plane windows other than the main
+    window. All drawing and mouse callbacks for your window will occur in
+    "boxels," giving your windows automatic support for high-DPI scaling in
+    X-Plane. In addition, your windows can opt-in to decoration with the
+    X-Plane 11 window styling, and you can use the
+    XPLMSetWindowPositioningMode() API to make your window "popped out" into a
+    first-class operating system window.
+    
+    Note that this requires dealing with your window's bounds in "global
+    desktop" positioning units, rather than the traditional panel coordinate
+    system. In global desktop coordinates, the main X-Plane window may not have
+    its origin at coordinate (0, 0), and your own window may have negative
+    coordinates. Assuming you don't implicitly assume (0, 0) as your origin,
+    the only API change you should need is to start using
+    XPLMGetMouseLocationGlobal() rather than XPLMGetMouseLocation(), and
+    XPLMGetScreenBoundsGlobal() instead of XPLMGetScreenSize().
+    
+    If you ask to be decorated as a floating window, you'll get the blue window
+    control bar and blue backing that you see in X-Plane 11's normal "floating"
+    windows (like the map).
+   }
+TYPE
+   XPLMCreateWindow_t = RECORD
+     { Used to inform XPLMCreateWindowEx() of the SDK version you compiled        }
+     { against; should always be set to sizeof(XPLMCreateWindow_t)                }
+     structSize               : Integer;
+     { Left bound, in global desktop boxels                                       }
+     left                     : Integer;
+     { Top bound, in global desktop boxels                                        }
+     top                      : Integer;
+     { Right bound, in global desktop boxels                                      }
+     right                    : Integer;
+     { Bottom bound, in global desktop boxels                                     }
+     bottom                   : Integer;
+     visible                  : Integer;
+     drawWindowFunc           : XPLMDrawWindow_f;
+     { A callback to handle the user left-clicking within your window (or NULL to }
+     { ignore left clicks)                                                        }
+     handleMouseClickFunc     : XPLMHandleMouseClick_f;
+     handleKeyFunc            : XPLMHandleKey_f;
+     handleCursorFunc         : XPLMHandleCursor_f;
+     handleMouseWheelFunc     : XPLMHandleMouseWheel_f;
+     { A reference which will be passed into each of your window callbacks. Use   }
+     { this to pass information to yourself as needed.                            }
+     refcon                   : pointer;
+{$IFDEF XPLM301}
+     { Specifies the type of X-Plane 11-style "wrapper" you want around your      }
+     { window, if any                                                             }
+     decorateAsFloatingWindow : XPLMWindowDecoration;
+{$ENDIF XPLM301}
+{$IFDEF XPLM300}
+     layer                    : XPLMWindowLayer;
+{$ENDIF XPLM300}
+{$IFDEF XPLM300}
+     { A callback to handle the user right-clicking within your window (or NULL to}
+     { ignore right clicks)                                                       }
+     handleRightClickFunc     : XPLMHandleMouseClick_f;
+{$ENDIF XPLM300}
+   END;
+   PXPLMCreateWindow_t = ^XPLMCreateWindow_t;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+   {
+    XPLMCreateWindowEx
+    
+    This routine creates a new "modern" window. You pass in an
+    XPLMCreateWindow_t structure with all of the fields set in.  You must set
+    the structSize of the structure to the size of the actual structure you
+    used.  Also, you must provide functions for every callback---you may not
+    leave them null!  (If you do not support the cursor or mouse wheel, use
+    functions that return the default values.)
+   }
+   FUNCTION XPLMCreateWindowEx(
+                                        inParams            : PXPLMCreateWindow_t) : XPLMWindowID;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+   {
+    XPLMCreateWindow
+    
+    Deprecated as of XPLM300.
+    
+    This routine creates a new legacy window. Unlike modern windows (created
+    via XPLMCreateWindowEx()), legacy windows do not have access to X-Plane 11
+    features like automatic scaling for high-DPI screens, native window styles,
+    or support for being "popped out" into first-class operating system
+    windows.
+    
+    Pass in the dimensions and offsets to the window's bottom left corner from
+    the bottom left of the screen.  You can specify whether the window is
+    initially visible or not.  Also, you pass in three callbacks to run the
+    window and a refcon.  This function returns a window ID you can use to
+    refer to the new window.
+    
+    NOTE: Legacy windows do not have "frames"; you are responsible for drawing
+    the background and frame of the window.  Higher level libraries have
+    routines which make this easy.
+   }
+   FUNCTION XPLMCreateWindow(
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer;
+                                        inIsVisible         : Integer;
+                                        inDrawCallback      : XPLMDrawWindow_f;
+                                        inKeyCallback       : XPLMHandleKey_f;
+                                        inMouseCallback     : XPLMHandleMouseClick_f;
+                                        inRefcon            : pointer) : XPLMWindowID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDestroyWindow
+    
+    This routine destroys a window.  The window's callbacks are not called
+    after this call. Keyboard focus is removed from the window before
+    destroying it.
+   }
+   PROCEDURE XPLMDestroyWindow(
+                                        inWindowID          : XPLMWindowID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetScreenSize
+    
+    This routine returns the size of the main X-Plane OpenGL window in pixels.
+    This number can be used to get a rough idea of the amount of detail the
+    user will be able to see when drawing in 3-d.
+   }
+   PROCEDURE XPLMGetScreenSize(
+                                        outWidth            : PInteger;    { Can be nil }
+                                        outHeight           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMGetScreenBoundsGlobal
+    
+    This routine returns the bounds of the "global" X-Plane desktop, in boxels.
+    Unlike the non-global version XPLMGetScreenSize(), this is multi-monitor
+    aware. There are three primary consequences of multimonitor awareness.
+    
+    First, if the user is running X-Plane in full-screen on two or more
+    monitors (typically configured using one full-screen window per monitor),
+    the global desktop will be sized to include all X-Plane windows.
+    
+    Second, the origin of the screen coordinates is not guaranteed to be (0,
+    0). Suppose the user has two displays side-by-side, both running at 1080p.
+    Suppose further that they've configured their OS to make the left display
+    their "primary" monitor, and that X-Plane is running in full-screen on
+    their right monitor only. In this case, the global desktop bounds would be
+    the rectangle from (1920, 0) to (3840, 1080). If the user later asked
+    X-Plane to draw on their primary monitor as well, the bounds would change
+    to (0, 0) to (3840, 1080).
+    
+    Finally, if the usable area of the virtual desktop is not a perfect
+    rectangle (for instance, because the monitors have different resolutions or
+    because one monitor is configured in the operating system to be above and
+    to the right of the other), the global desktop will include any wasted
+    space. Thus, if you have two 1080p monitors, and monitor 2 is configured to
+    have its bottom left touch monitor 1's upper right, your global desktop
+    area would be the rectangle from (0, 0) to (3840, 2160).
+    
+    Note that popped-out windows (windows drawn in their own operating system
+    windows, rather than "floating" within X-Plane) are not included in these
+    bounds.
+   }
+   PROCEDURE XPLMGetScreenBoundsGlobal(
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMReceiveMonitorBoundsGlobal_f
+    
+    This function is informed of the global bounds (in boxels) of a particular
+    monitor within the X-Plane global desktop space. Note that X-Plane must be
+    running in full screen on a monitor in order for that monitor to be passed
+    to you in this callback.
+   }
+TYPE
+     XPLMReceiveMonitorBoundsGlobal_f = PROCEDURE(
+                                    inMonitorIndex      : Integer;
+                                    inLeftBx            : Integer;
+                                    inTopBx             : Integer;
+                                    inRightBx           : Integer;
+                                    inBottomBx          : Integer;
+                                    inRefcon            : pointer); cdecl;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMGetAllMonitorBoundsGlobal
+    
+    This routine immediately calls you back with the bounds (in boxels) of each
+    full-screen X-Plane window within the X-Plane global desktop space. Note
+    that if a monitor is *not* covered by an X-Plane window, you cannot get its
+    bounds this way. Likewise, monitors with only an X-Plane window (not in
+    full-screen mode) will not be included.
+    
+    If X-Plane is running in full-screen and your monitors are of the same size
+    and configured contiguously in the OS, then the combined global bounds of
+    all full-screen monitors will match the total global desktop bounds, as
+    returned by XPLMGetScreenBoundsGlobal(). (Of course, if X-Plane is running
+    in windowed mode, this will not be the case. Likewise, if you have
+    differently sized monitors, the global desktop space will include wasted
+    space.)
+    
+    Note that this function's monitor indices match those provided by
+    XPLMGetAllMonitorBoundsOS(), but the coordinates are different (since the
+    X-Plane global desktop may not match the operating system's global desktop,
+    and one X-Plane boxel may be larger than one pixel due to 150% or 200%
+    scaling).
+   }
+   PROCEDURE XPLMGetAllMonitorBoundsGlobal(
+                                        inMonitorBoundsCallback: XPLMReceiveMonitorBoundsGlobal_f;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMReceiveMonitorBoundsOS_f
+    
+    This function is informed of the global bounds (in pixels) of a particular
+    monitor within the operating system's global desktop space. Note that a
+    monitor index being passed to you here does not indicate that X-Plane is
+    running in full screen on this monitor, or even that any X-Plane windows
+    exist on this monitor.
+   }
+TYPE
+     XPLMReceiveMonitorBoundsOS_f = PROCEDURE(
+                                    inMonitorIndex      : Integer;
+                                    inLeftPx            : Integer;
+                                    inTopPx             : Integer;
+                                    inRightPx           : Integer;
+                                    inBottomPx          : Integer;
+                                    inRefcon            : pointer); cdecl;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMGetAllMonitorBoundsOS
+    
+    This routine immediately calls you back with the bounds (in pixels) of each
+    monitor within the operating system's global desktop space. Note that
+    unlike XPLMGetAllMonitorBoundsGlobal(), this may include monitors that have
+    no X-Plane window on them.
+    
+    Note that this function's monitor indices match those provided by
+    XPLMGetAllMonitorBoundsGlobal(), but the coordinates are different (since
+    the X-Plane global desktop may not match the operating system's global
+    desktop, and one X-Plane boxel may be larger than one pixel).
+   }
+   PROCEDURE XPLMGetAllMonitorBoundsOS(
+                                        inMonitorBoundsCallback: XPLMReceiveMonitorBoundsOS_f;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+   {
+    XPLMGetMouseLocation
+    
+    Deprecated in XPLM300. Modern windows should use
+    XPLMGetMouseLocationGlobal() instead.
+    
+    This routine returns the current mouse location in pixels relative to the
+    main X-Plane window. The bottom left corner of the main window is (0, 0). 
+    Pass NULL to not receive info about either parameter.
+    
+    Because this function gives the mouse position relative to the main X-Plane
+    window (rather than in global bounds), this function should only be used by
+    legacy windows. Modern windows should instead get the mouse position in
+    global desktop coordinates using XPLMGetMouseLocationGlobal().
+    
+    Note that unlike XPLMGetMouseLocationGlobal(), if the mouse goes outside
+    the user's main monitor (for instance, to a pop out window or a secondary
+    monitor), this function will not reflect it.
+   }
+   PROCEDURE XPLMGetMouseLocation(
+                                        outX                : PInteger;    { Can be nil }
+                                        outY                : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMGetMouseLocationGlobal
+    
+    Returns the current mouse location in global desktop boxels. Unlike
+    XPLMGetMouseLocation(), the bottom left of the main X-Plane window is not
+    guaranteed to be (0, 0)---instead, the origin is the lower left of the
+    entire global desktop space. In addition, this routine gives the real mouse
+    location when the mouse goes to X-Plane windows other than the primary
+    display. Thus, it can be used with both pop-out windows and secondary
+    monitors.
+    
+    This is the mouse location function to use with modern windows (i.e., those
+    created by XPLMCreateWindowEx()).
+    
+    Pass NULL to not receive info about either parameter.
+   }
+   PROCEDURE XPLMGetMouseLocationGlobal(
+                                        outX                : PInteger;    { Can be nil }
+                                        outY                : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+   {
+    XPLMGetWindowGeometry
+    
+    This routine returns the position and size of a window. The units and
+    coordinate system vary depending on the type of window you have.
+    
+    If this is a legacy window (one compiled against a pre-XPLM300 version of
+    the SDK, or an XPLM300 window that was not created using
+    XPLMCreateWindowEx()), the units are pixels relative to the main X-Plane
+    display.
+    
+    If, on the other hand, this is a new X-Plane 11-style window (compiled
+    against the XPLM300 SDK and created using XPLMCreateWindowEx()), the units
+    are global desktop boxels.
+    
+    Pass NULL to not receive any paramter.
+   }
+   PROCEDURE XPLMGetWindowGeometry(
+                                        inWindowID          : XPLMWindowID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetWindowGeometry
+    
+    This routine allows you to set the position and size of a window.
+    
+    The units and coordinate system match those of XPLMGetWindowGeometry().
+    That is, modern windows use global desktop boxel coordinates, while legacy
+    windows use pixels relative to the main X-Plane display.
+    
+    Note that this only applies to "floating" windows (that is, windows that
+    are drawn within the X-Plane simulation windows, rather than being "popped
+    out" into their own first-class operating system windows). To set the
+    position of windows whose positioning mode is xplm_WindowPopOut, you'll
+    need to instead use XPLMSetWindowGeometryOS().
+   }
+   PROCEDURE XPLMSetWindowGeometry(
+                                        inWindowID          : XPLMWindowID;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMGetWindowGeometryOS
+    
+    This routine returns the position and size of a "popped out" window (i.e.,
+    a window whose positioning mode is xplm_WindowPopOut), in operating system
+    pixels.  Pass NULL to not receive any parameter.
+   }
+   PROCEDURE XPLMGetWindowGeometryOS(
+                                        inWindowID          : XPLMWindowID;
+                                        outLeft             : PInteger;    { Can be nil }
+                                        outTop              : PInteger;    { Can be nil }
+                                        outRight            : PInteger;    { Can be nil }
+                                        outBottom           : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMSetWindowGeometryOS
+    
+    This routine allows you to set the position and size, in operating system
+    pixel coordinates, of a popped out window (that is, a window whose
+    positioning mode is xplm_WindowPopOut, which exists outside the X-Plane
+    simulation window, in its own first-class operating system window).
+    
+    Note that you are responsible for ensuring both that your window is popped
+    out (using XPLMWindowIsPoppedOut()) and that a monitor really exists at the
+    OS coordinates you provide (using XPLMGetAllMonitorBoundsOS()).
+   }
+   PROCEDURE XPLMSetWindowGeometryOS(
+                                        inWindowID          : XPLMWindowID;
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM301}
+   {
+    XPLMGetWindowGeometryVR
+    
+    Returns the width and height, in boxels, of a window in VR. Note that you
+    are responsible for ensuring your window is in VR (using
+    XPLMWindowIsInVR()).
+   }
+   PROCEDURE XPLMGetWindowGeometryVR(
+                                        inWindowID          : XPLMWindowID;
+                                        outWidthBoxels      : PInteger;    { Can be nil }
+                                        outHeightBoxels     : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM301}
+
+{$IFDEF XPLM301}
+   {
+    XPLMSetWindowGeometryVR
+    
+    This routine allows you to set the size, in boxels, of a window in VR (that
+    is, a window whose positioning mode is xplm_WindowVR).
+    
+    Note that you are responsible for ensuring your window is in VR (using
+    XPLMWindowIsInVR()).
+   }
+   PROCEDURE XPLMSetWindowGeometryVR(
+                                        inWindowID          : XPLMWindowID;
+                                        widthBoxels         : Integer;
+                                        heightBoxels        : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM301}
+
+   {
+    XPLMGetWindowIsVisible
+    
+    Returns true (1) if the specified window is visible.
+   }
+   FUNCTION XPLMGetWindowIsVisible(
+                                        inWindowID          : XPLMWindowID) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetWindowIsVisible
+    
+    This routine shows or hides a window.
+   }
+   PROCEDURE XPLMSetWindowIsVisible(
+                                        inWindowID          : XPLMWindowID;
+                                        inIsVisible         : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMWindowIsPoppedOut
+    
+    True if this window has been popped out (making it a first-class window in
+    the operating system), which in turn is true if and only if you have set
+    the window's positioning mode to xplm_WindowPopOut.
+    
+    Only applies to modern windows. (Windows created using the deprecated
+    XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+    the SDK cannot be popped out.)
+   }
+   FUNCTION XPLMWindowIsPoppedOut(
+                                        inWindowID          : XPLMWindowID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM301}
+   {
+    XPLMWindowIsInVR
+    
+    True if this window has been moved to the virtual reality (VR) headset,
+    which in turn is true if and only if you have set the window's positioning
+    mode to xplm_WindowVR.
+    
+    Only applies to modern windows. (Windows created using the deprecated
+    XPLMCreateWindow(), or windows compiled against a pre-XPLM301 version of
+    the SDK cannot be moved to VR.)
+   }
+   FUNCTION XPLMWindowIsInVR(
+                                        inWindowID          : XPLMWindowID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM301}
+
+{$IFDEF XPLM300}
+   {
+    XPLMSetWindowGravity
+    
+    A window's "gravity" controls how the window shifts as the whole X-Plane
+    window resizes. A gravity of 1 means the window maintains its positioning
+    relative to the right or top edges, 0 the left/bottom, and 0.5 keeps it
+    centered.
+    
+    Default gravity is (0, 1, 0, 1), meaning your window will maintain its
+    position relative to the top left and will not change size as its
+    containing window grows.
+    
+    If you wanted, say, a window that sticks to the top of the screen (with a
+    constant height), but which grows to take the full width of the window, you
+    would pass (0, 1, 1, 1). Because your left and right edges would maintain
+    their positioning relative to their respective edges of the screen, the
+    whole width of your window would change with the X-Plane window.
+    
+    Only applies to modern windows. (Windows created using the deprecated
+    XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+    the SDK will simply get the default gravity.)
+   }
+   PROCEDURE XPLMSetWindowGravity(
+                                        inWindowID          : XPLMWindowID;
+                                        inLeftGravity       : Single;
+                                        inTopGravity        : Single;
+                                        inRightGravity      : Single;
+                                        inBottomGravity     : Single);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMSetWindowResizingLimits
+    
+    Sets the minimum and maximum size of the client rectangle of the given
+    window. (That is, it does not include any window styling that you might
+    have asked X-Plane to apply on your behalf.) All resizing operations are
+    constrained to these sizes.
+    
+    Only applies to modern windows. (Windows created using the deprecated
+    XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+    the SDK will have no minimum or maximum size.)
+   }
+   PROCEDURE XPLMSetWindowResizingLimits(
+                                        inWindowID          : XPLMWindowID;
+                                        inMinWidthBoxels    : Integer;
+                                        inMinHeightBoxels   : Integer;
+                                        inMaxWidthBoxels    : Integer;
+                                        inMaxHeightBoxels   : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMWindowPositioningMode
+    
+    XPLMWindowPositionMode describes how X-Plane will position your window on
+    the user's screen. X-Plane will maintain this positioning mode even as the
+    user resizes their window or adds/removes full-screen monitors.
+    
+    Positioning mode can only be set for "modern" windows (that is, windows
+    created using XPLMCreateWindowEx() and compiled against the XPLM300 SDK).
+    Windows created using the deprecated XPLMCreateWindow(), or windows
+    compiled against a pre-XPLM300 version of the SDK will simply get the
+    "free" positioning mode.
+   }
+TYPE
+   XPLMWindowPositioningMode = (
+     { The default positioning mode. Set the window geometry and its future       }
+     { position will be determined by its window gravity, resizing limits, and    }
+     { user interactions.                                                         }
+      xplm_WindowPositionFree                  = 0
+ 
+     { Keep the window centered on the monitor you specify                        }
+     ,xplm_WindowCenterOnMonitor               = 1
+ 
+     { Keep the window full screen on the monitor you specify                     }
+     ,xplm_WindowFullScreenOnMonitor           = 2
+ 
+     { Like gui_window_full_screen_on_monitor, but stretches over *all* monitors  }
+     { and popout windows. This is an obscure one... unless you have a very good  }
+     { reason to need it, you probably don't!                                     }
+     ,xplm_WindowFullScreenOnAllMonitors       = 3
+ 
+     { A first-class window in the operating system, completely separate from the }
+     { X-Plane window(s)                                                          }
+     ,xplm_WindowPopOut                        = 4
+ 
+{$IFDEF XPLM301}
+     { A floating window visible on the VR headset                                }
+     ,xplm_WindowVR                            = 5
+{$ENDIF XPLM301}
+ 
+   );
+   PXPLMWindowPositioningMode = ^XPLMWindowPositioningMode;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMSetWindowPositioningMode
+    
+    Sets the policy for how X-Plane will position your window.
+    
+    Some positioning modes apply to a particular monitor. For those modes, you
+    can pass a negative monitor index to position the window on the main
+    X-Plane monitor (the screen with the X-Plane menu bar at the top). Or, if
+    you have a specific monitor you want to position your window on, you can
+    pass a real monitor index as received from, e.g.,
+    XPLMGetAllMonitorBoundsOS().
+    
+    Only applies to modern windows. (Windows created using the deprecated
+    XPLMCreateWindow(), or windows compiled against a pre-XPLM300 version of
+    the SDK will always use xplm_WindowPositionFree.)
+   }
+   PROCEDURE XPLMSetWindowPositioningMode(
+                                        inWindowID          : XPLMWindowID;
+                                        inPositioningMode   : XPLMWindowPositioningMode;
+                                        inMonitorIndex      : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+{$IFDEF XPLM300}
+   {
+    XPLMSetWindowTitle
+    
+    Sets the name for a window. This only applies to windows that opted-in to
+    styling as an X-Plane 11 floating window (i.e., with styling mode
+    xplm_WindowDecorationRoundRectangle) when they were created using
+    XPLMCreateWindowEx().
+   }
+   PROCEDURE XPLMSetWindowTitle(
+                                        inWindowID          : XPLMWindowID;
+                                        inWindowTitle       : XPLMString);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+   {
+    XPLMGetWindowRefCon
+    
+    Returns a window's reference constant, the unique value you can use for
+    your own purposes.
+   }
+   FUNCTION XPLMGetWindowRefCon(
+                                        inWindowID          : XPLMWindowID) : pointer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetWindowRefCon
+    
+    Sets a window's reference constant.  Use this to pass data to yourself in
+    the callbacks.
+   }
+   PROCEDURE XPLMSetWindowRefCon(
+                                        inWindowID          : XPLMWindowID;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMTakeKeyboardFocus
+    
+    This routine gives a specific window keyboard focus.  Keystrokes will be
+    sent to that window.  Pass a window ID of 0 to remove keyboard focus from
+    any plugin-created windows and instead pass keyboard strokes directly to
+    X-Plane.
+   }
+   PROCEDURE XPLMTakeKeyboardFocus(
+                                        inWindow            : XPLMWindowID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMHasKeyboardFocus
+    
+    Returns true (1) if the indicated window has keyboard focus. Pass a window
+    ID of 0 to see if no plugin window has focus, and all keystrokes will go
+    directly to X-Plane.
+   }
+   FUNCTION XPLMHasKeyboardFocus(
+                                        inWindow            : XPLMWindowID) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMBringWindowToFront
+    
+    This routine brings the window to the front of the Z-order for its layer. 
+    Windows are brought to the front automatically when they are created.
+    Beyond that, you should make sure you are front before handling mouse
+    clicks.
+    
+    Note that this only brings your window to the front of its layer
+    (XPLMWindowLayer). Thus, if you have a window in the floating window layer
+    (xplm_WindowLayerFloatingWindows), but there is a modal window (in layer
+    xplm_WindowLayerModal) above you, you would still not be the true frontmost
+    window after calling this. (After all, the window layers are strictly
+    ordered, and no window in a lower layer can ever be above any window in a
+    higher one.)
+   }
+   PROCEDURE XPLMBringWindowToFront(
+                                        inWindow            : XPLMWindowID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMIsWindowInFront
+    
+    This routine returns true if the window you passed in is the frontmost
+    visible window in its layer (XPLMWindowLayer).
+    
+    Thus, if you have a window at the front of the floating window layer
+    (xplm_WindowLayerFloatingWindows), this will return true even if there is a
+    modal window (in layer xplm_WindowLayerModal) above you. (Not to worry,
+    though: in such a case, X-Plane will not pass clicks or keyboard input down
+    to your layer until the window above stops "eating" the input.)
+    
+    Note that legacy windows are always placed in layer
+    xplm_WindowLayerFlightOverlay, while modern-style windows default to
+    xplm_WindowLayerFloatingWindows. This means it's perfectly consistent to
+    have two different plugin-created windows (one legacy, one modern) *both*
+    be in the front (of their different layers!) at the same time.
+   }
+   FUNCTION XPLMIsWindowInFront(
+                                        inWindow            : XPLMWindowID) : Integer;
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * KEY SNIFFERS
+ ___________________________________________________________________________}
+{
+   Low-level keyboard handlers. Allows for intercepting keystrokes outside the
+   normal rules of the user interface.
+}
+
+
+   {
+    XPLMKeySniffer_f
+    
+    This is the prototype for a low level key-sniffing function.  Window-based
+    UI _should not use this_!  The windowing system provides high-level
+    mediated keyboard access, via the callbacks you attach to your
+    XPLMCreateWindow_t. By comparison, the key sniffer provides low level
+    keyboard access.
+    
+    Key sniffers are provided to allow libraries to provide non-windowed user
+    interaction.  For example, the MUI library uses a key sniffer to do pop-up
+    text entry.
+    
+    Return 1 to pass the key on to the next sniffer, the window manager,
+    X-Plane, or whomever is down stream.  Return 0 to consume the key.
+    
+    Warning: this API declares virtual keys as a signed character; however the
+    VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values
+    (that is 0x80 instead of -0x80).  So you may need to cast the incoming vkey
+    to an unsigned char to get correct comparisons in C.
+   }
+TYPE
+     XPLMKeySniffer_f = FUNCTION(
+                                    inChar              : XPLMChar;
+                                    inFlags             : XPLMKeyFlags;
+                                    inVirtualKey        : XPLMChar;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+   {
+    XPLMRegisterKeySniffer
+    
+    This routine registers a key sniffing callback.  You specify whether you
+    want to sniff before the window system, or only sniff keys the window
+    system does not consume.  You should ALMOST ALWAYS sniff non-control keys
+    after the window system.  When the window system consumes a key, it is
+    because the user has "focused" a window.  Consuming the key or taking
+    action based on the key will produce very weird results.  Returns
+    1 if successful.
+   }
+   FUNCTION XPLMRegisterKeySniffer(
+                                        inCallback          : XPLMKeySniffer_f;
+                                        inBeforeWindows     : Integer;
+                                        inRefcon            : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterKeySniffer
+    
+    This routine unregisters a key sniffer.  You must unregister a key sniffer
+    for every time you register one with the exact same signature.  Returns 1
+    if successful.
+   }
+   FUNCTION XPLMUnregisterKeySniffer(
+                                        inCallback          : XPLMKeySniffer_f;
+                                        inBeforeWindows     : Integer;
+                                        inRefcon            : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * HOT KEYS
+ ___________________________________________________________________________}
+{
+   Keystrokes that can be managed by others. These are lower-level than window
+   keyboard handlers (i.e., callbacks you attach to your XPLMCreateWindow_t),
+   but higher level than key sniffers.
+}
+
+
+   {
+    XPLMHotKey_f
+    
+    Your hot key callback simply takes a pointer of your choosing.
+   }
+TYPE
+     XPLMHotKey_f = PROCEDURE(
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMHotKeyID
+    
+    An opaque ID used to identify a hot key.
+   }
+   XPLMHotKeyID = pointer;
+   PXPLMHotKeyID = ^XPLMHotKeyID;
+
+   {
+    XPLMRegisterHotKey
+    
+    This routine registers a hot key.  You specify your preferred key stroke
+    virtual key/flag combination, a description of what your callback does (so
+    other plug-ins can describe the plug-in to the user for remapping) and a
+    callback function and opaque pointer to pass in).  A new hot key ID is
+    returned.  During execution, the actual key associated with your hot key
+    may change, but you are insulated from this.
+   }
+   FUNCTION XPLMRegisterHotKey(
+                                        inVirtualKey        : XPLMChar;
+                                        inFlags             : XPLMKeyFlags;
+                                        inDescription       : XPLMString;
+                                        inCallback          : XPLMHotKey_f;
+                                        inRefcon            : pointer) : XPLMHotKeyID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterHotKey
+    
+    Unregisters a hot key.  You can only unregister your own hot keys.
+   }
+   PROCEDURE XPLMUnregisterHotKey(
+                                        inHotKey            : XPLMHotKeyID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCountHotKeys
+    
+    Returns the number of current hot keys.
+   }
+   FUNCTION XPLMCountHotKeys: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetNthHotKey
+    
+    Returns a hot key by index, for iteration on all hot keys.
+   }
+   FUNCTION XPLMGetNthHotKey(
+                                        inIndex             : Integer) : XPLMHotKeyID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetHotKeyInfo
+    
+    Returns information about the hot key.  Return NULL for any parameter you
+    don't want info about.  The description should be at least 512 chars long.
+   }
+   PROCEDURE XPLMGetHotKeyInfo(
+                                        inHotKey            : XPLMHotKeyID;
+                                        outVirtualKey       : XPLMString;    { Can be nil }
+                                        outFlags            : PXPLMKeyFlags;    { Can be nil }
+                                        outDescription      : XPLMString;    { Can be nil }
+                                        outPlugin           : PXPLMPluginID);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetHotKeyCombination
+    
+    Remaps a hot key's keystrokes.  You may remap another plugin's keystrokes.
+   }
+   PROCEDURE XPLMSetHotKeyCombination(
+                                        inHotKey            : XPLMHotKeyID;
+                                        inVirtualKey        : XPLMChar;
+                                        inFlags             : XPLMKeyFlags);
+    cdecl; external XPLM_DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMGraphics.pas b/SDK/Delphi/XPLM/XPLMGraphics.pas
new file mode 100644
index 0000000..90d9480
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMGraphics.pas
@@ -0,0 +1,424 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMGraphics;
+INTERFACE
+{
+   A few notes on coordinate systems:
+   
+   X-Plane uses three kinds of coordinates.  Global coordinates are specified
+   as latitude, longitude and elevation.  This coordinate system never changes
+   but is not very precise.
+   
+   OpenGL (or 'local') coordinates are cartesian and move with the aircraft. 
+   They offer more precision and are used for 3-d OpenGL drawing.  The X axis
+   is aligned east-west with positive X meaning east.  The Y axis is aligned
+   straight up and down at the point 0,0,0 (but since the Earth is round it is
+   not truly straight up and down at other points).  The Z axis is aligned
+   north-south at 0, 0, 0 with positive Z pointing south (but since the Earth
+   is round it isn't exactly north-south as you move east or west of 0, 0, 0).
+   One unit is one meter and the point 0,0,0 is on the surface of the Earth at
+   sea level for some latitude and longitude picked by the sim such that the
+   user's aircraft is reasonably nearby.
+   
+   2-d Panel coordinates are 2d, with the X axis horizontal and the Y axis
+     vertical. The point 0,0 is the bottom left and 1024,768 is the upper
+     right of the screen. This is true no matter what resolution the user's
+     monitor is in; when running in higher resolution, graphics will be
+     scaled.
+   
+   Use X-Plane's routines to convert between global and local coordinates.  Do
+   not attempt to do this conversion yourself; the precise 'roundness' of
+   X-Plane's physics model may not match your own, and (to make things
+   weirder) the user can potentially customize the physics of the current
+   planet.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * X-PLANE GRAPHICS
+ ___________________________________________________________________________}
+{
+   These routines allow you to use OpenGL with X-Plane.
+}
+
+
+   {
+    XPLMTextureID
+    
+    XPLM Texture IDs name well-known textures in the sim for you to use. This
+    allows you to recycle textures from X-Plane, saving VRAM.
+    
+    *Warning*: do not use these enums.  The only remaining use they have is to
+     access the legacy compatibility v10 UI texture; if you need this, get it
+     via the Widgets library.
+   }
+TYPE
+   XPLMTextureID = (
+     { The bitmap that contains window outlines, button outlines, fonts, etc.     }
+      xplm_Tex_GeneralInterface                = 0
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { The exterior paint for the user's aircraft (daytime).                      }
+     ,xplm_Tex_AircraftPaint                   = 1
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { The exterior light map for the user's aircraft.                            }
+     ,xplm_Tex_AircraftLiteMap                 = 2
+{$ENDIF XPLM_DEPRECATED}
+ 
+   );
+   PXPLMTextureID = ^XPLMTextureID;
+
+   {
+    XPLMSetGraphicsState
+    
+    XPLMSetGraphicsState changes OpenGL's fixed function pipeline state.  You
+    are not responsible for restoring any state that is accessed via
+    XPLMSetGraphicsState, but you are responsible for not accessing this state
+    directly.
+    
+    - inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG);
+    - inNumberTexUnits - enables or disables a number of multitexturing units.
+      If the number is 0, 2d texturing is disabled entirely, as in
+      glDisable(GL_TEXTURE_2D);  Otherwise, 2d texturing is enabled, and a
+      number of multitexturing units are enabled sequentially, starting with
+      unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable
+      (GL_TEXTURE_2D);
+    - inEnableLighting - enables or disables OpenGL lighting, e.g.
+      glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
+    - inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g.
+      glEnable(GL_ALPHA_TEST);
+    - inEnableAlphaBlending - enables or disables alpha blending per pixel,
+      e.g. glEnable(GL_BLEND);
+    - inEnableDepthTesting - enables per pixel depth testing, as in
+      glEnable(GL_DEPTH_TEST);
+    - inEnableDepthWriting - enables writing back of depth information to the
+      depth buffer, as in glDepthMask(GL_TRUE);
+    
+    The purpose of this function is to change OpenGL state while keeping
+    X-Plane aware of the state changes; this keeps X-Plane from getting
+    surprised by OGL state changes, and prevents X-Plane and plug-ins from
+    having to set all state before all draws; XPLMSetGraphicsState internally
+    skips calls to change state that is already properly enabled.
+    
+    X-Plane does not have a 'default' OGL state for plug-ins with respect to
+    the above state vector; plug-ins should totally set OGL state using this
+    API before drawing.  Use XPLMSetGraphicsState instead of any of the above
+    OpenGL calls.
+    
+    WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget
+    code) may change X-Plane's state.  Always set state before drawing after
+    unknown code has executed.
+    
+    *Deprecation Warnings*: X-Plane's lighting and fog environment is
+     significantly more complex than the fixed function pipeline can express;
+     do not assume that lighting and fog state is a good approximation for 3-d
+     drawing.  Prefer to use XPLMInstancing to draw objects.  All calls to
+     XPLMSetGraphicsState should have no fog or lighting.
+   }
+   PROCEDURE XPLMSetGraphicsState(
+                                        inEnableFog         : Integer;
+                                        inNumberTexUnits    : Integer;
+                                        inEnableLighting    : Integer;
+                                        inEnableAlphaTesting: Integer;
+                                        inEnableAlphaBlending: Integer;
+                                        inEnableDepthTesting: Integer;
+                                        inEnableDepthWriting: Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMBindTexture2d
+    
+     XPLMBindTexture2d changes what texture is bound to the 2d texturing
+     target. This routine caches the current 2d texture across all texturing
+     units in the sim and plug-ins, preventing extraneous binding.  For
+     example, consider several plug-ins running in series; if they all use the
+     'general interface' bitmap to do UI, calling this function will skip the
+     rebinding of the general interface texture on all but the first plug-in,
+     which can provide better frame rates on some graphics cards.
+    
+    inTextureID is the ID of the texture object to bind; inTextureUnit is a
+    zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4
+    units.  (This number may increase in future versions of X-Plane.)
+    
+    Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....);
+   }
+   PROCEDURE XPLMBindTexture2d(
+                                        inTextureNum        : Integer;
+                                        inTextureUnit       : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGenerateTextureNumbers
+    
+    Use this routine instead of glGenTextures to generate new texture object
+    IDs. This routine historically ensured that plugins don't use texure IDs
+    that X-Plane is reserving for its own use.
+   }
+   PROCEDURE XPLMGenerateTextureNumbers(
+                                        outTextureIDs       : PInteger;
+                                        inCount             : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMGetTexture
+    
+    XPLMGetTexture returns the OpenGL texture ID of an X-Plane texture based on
+    a generic identifying code.  For example, you can get the texture for
+    X-Plane's UI bitmaps.
+   }
+   FUNCTION XPLMGetTexture(
+                                        inTexture           : XPLMTextureID) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM_DEPRECATED}
+
+   {
+    XPLMWorldToLocal
+    
+    This routine translates coordinates from latitude, longitude, and altitude
+    to local scene coordinates. Latitude and longitude are in decimal degrees,
+    and altitude is in meters MSL (mean sea level).  The XYZ coordinates are in
+    meters in the local OpenGL coordinate system.
+   }
+   PROCEDURE XPLMWorldToLocal(
+                                        inLatitude          : Real;
+                                        inLongitude         : Real;
+                                        inAltitude          : Real;
+                                        outX                : PReal;
+                                        outY                : PReal;
+                                        outZ                : PReal);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMLocalToWorld
+    
+    This routine translates a local coordinate triplet back into latitude,
+    longitude, and altitude.  Latitude and longitude are in decimal degrees,
+    and altitude is in meters MSL (mean sea level).  The XYZ coordinates are in
+    meters in the local OpenGL coordinate system.
+    
+    NOTE: world coordinates are less precise than local coordinates; you should
+    try to avoid round tripping from local to world and back.
+   }
+   PROCEDURE XPLMLocalToWorld(
+                                        inX                 : Real;
+                                        inY                 : Real;
+                                        inZ                 : Real;
+                                        outLatitude         : PReal;
+                                        outLongitude        : PReal;
+                                        outAltitude         : PReal);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDrawTranslucentDarkBox
+    
+    This routine draws a translucent dark box, partially obscuring parts of the
+    screen but making text easy to read.  This is the same graphics primitive
+    used by X-Plane to show text files.
+   }
+   PROCEDURE XPLMDrawTranslucentDarkBox(
+                                        inLeft              : Integer;
+                                        inTop               : Integer;
+                                        inRight             : Integer;
+                                        inBottom            : Integer);
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * X-PLANE TEXT
+ ___________________________________________________________________________}
+
+   {
+    XPLMFontID
+    
+    X-Plane features some fixed-character fonts.  Each font may have its own
+    metrics.
+    
+    WARNING: Some of these fonts are no longer supported or may have changed
+    geometries. For maximum copmatibility, see the comments below.
+    
+    Note: X-Plane 7 supports proportional-spaced fonts.  Since no measuring
+    routine is available yet, the SDK will normally draw using a fixed-width
+    font.  You can use a dataref to enable proportional font drawing on XP7 if
+    you want to.
+   }
+TYPE
+   XPLMFontID = (
+     { Mono-spaced font for user interface.  Available in all versions of the SDK.}
+      xplmFont_Basic                           = 0
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_Menus                           = 1
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_Metal                           = 2
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_Led                             = 3
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_LedWide                         = 4
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_PanelHUD                        = 5
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_PanelEFIS                       = 6
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_PanelGPS                        = 7
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosGA                        = 8
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosBC                        = 9
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosHM                        = 10
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosGANarrow                  = 11
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosBCNarrow                  = 12
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_RadiosHMNarrow                  = 13
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_Timer                           = 14
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_FullRound                       = 15
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_SmallRound                      = 16
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     { Deprecated, do not use.                                                    }
+     ,xplmFont_Menus_Localized                 = 17
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM200}
+     { Proportional UI font.                                                      }
+     ,xplmFont_Proportional                    = 18
+{$ENDIF XPLM200}
+ 
+   );
+   PXPLMFontID = ^XPLMFontID;
+
+   {
+    XPLMDrawString
+    
+    This routine draws a NULL terminated string in a given font.  Pass in the
+    lower left pixel that the character is to be drawn onto.  Also pass the
+    character and font ID. This function returns the x offset plus the width of
+    all drawn characters. The color to draw in is specified as a pointer to an
+    array of three floating point colors, representing RGB intensities from 0.0
+    to 1.0.
+   }
+   PROCEDURE XPLMDrawString(
+                                        inColorRGB          : PSingle;
+                                        inXOffset           : Integer;
+                                        inYOffset           : Integer;
+                                        inChar              : XPLMString;
+                                        inWordWrapWidth     : PInteger;    { Can be nil }
+                                        inFontID            : XPLMFontID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDrawNumber
+    
+    This routine draws a number similar to the digit editing fields in
+    PlaneMaker and data output display in X-Plane.  Pass in a color, a
+    position, a floating point value, and formatting info.  Specify how many
+    integer and how many decimal digits to show and whether to show a sign, as
+    well as a character set. This routine returns the xOffset plus width of the
+    string drawn.
+   }
+   PROCEDURE XPLMDrawNumber(
+                                        inColorRGB          : PSingle;
+                                        inXOffset           : Integer;
+                                        inYOffset           : Integer;
+                                        inValue             : Real;
+                                        inDigits            : Integer;
+                                        inDecimals          : Integer;
+                                        inShowSign          : Integer;
+                                        inFontID            : XPLMFontID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetFontDimensions
+    
+    This routine returns the width and height of a character in a given font.
+    It also tells you if the font only supports numeric digits.  Pass NULL if
+    you don't need a given field.  Note that for a proportional font the width
+    will be an arbitrary, hopefully average width.
+   }
+   PROCEDURE XPLMGetFontDimensions(
+                                        inFontID            : XPLMFontID;
+                                        outCharWidth        : PInteger;    { Can be nil }
+                                        outCharHeight       : PInteger;    { Can be nil }
+                                        outDigitsOnly       : PInteger);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM200}
+   {
+    XPLMMeasureString
+    
+    This routine returns the width in pixels of a string using a given font. 
+    The string is passed as a pointer plus length (and does not need to be null
+    terminated); this is used to allow for measuring substrings. The return
+    value is floating point; it is possible that future font drawing may allow
+    for fractional pixels.
+   }
+   FUNCTION XPLMMeasureString(
+                                        inFontID            : XPLMFontID;
+                                        inChar              : XPLMString;
+                                        inNumChars          : Integer) : Single;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMInstance.pas b/SDK/Delphi/XPLM/XPLMInstance.pas
new file mode 100644
index 0000000..75da2bc
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMInstance.pas
@@ -0,0 +1,125 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMInstance;
+INTERFACE
+{
+   This API provides instanced drawing of X-Plane objects (.obj files). In
+   contrast to old drawing APIs, which required you to draw your own objects
+   per-frame, the instancing API allows you to simply register an OBJ for
+   drawing, then move or manipulate it later (as needed).
+   
+   This provides one tremendous benefit: it keeps all dataref operations for
+   your object in one place. Because datarefs access may be done from the main
+   thread only, allowing dataref access anywhere is a serious performance
+   bottleneck for the simulator - the whole simulator has to pause and wait
+   for each dataref access. This performance penalty will only grow worse as
+   X-Plane moves toward an ever more heavily multithreaded engine.
+   
+   The instancing API allows X-Plane to isolate all dataref manipulations for
+   all plugin object drawing to one place, potentially providing huge
+   performance gains.
+   
+   Here's how it works:
+   
+   When an instance is created, it provides a list of all datarefs you want to
+   manipulate for the OBJ in the future. This list of datarefs replaces the
+   ad-hoc collections of dataref objects previously used by art assets. Then,
+   per-frame, you can manipulate the instance by passing in a "block" of
+   packed floats representing the current values of the datarefs for your
+   instance. (Note that the ordering of this set of packed floats must exactly
+   match the ordering of the datarefs when you created your instance.)
+}
+
+USES
+    XPLMDefs, XPLMScenery;
+   {$A4}
+{___________________________________________________________________________
+ * Instance Creation and Destruction
+ ___________________________________________________________________________}
+{
+   Registers and unregisters instances.
+}
+
+
+TYPE
+   {
+    XPLMInstanceRef
+    
+    An opaque handle to an instance.
+   }
+   XPLMInstanceRef = pointer;
+   PXPLMInstanceRef = ^XPLMInstanceRef;
+
+   {
+    XPLMCreateInstance
+    
+    XPLMCreateInstance creates a new instance, managed by your plug-in, and
+    returns a handle to the instance. A few important requirements:
+    
+    * The object passed in must be fully loaded and returned from the XPLM
+      before you can create your instance; you cannot pass a null obj ref, nor
+      can you change the ref later.
+    
+    * If you use any custom datarefs in your object, they must be registered
+      before the object is loaded. This is true even if their data will be
+      provided via the instance dataref list.
+    
+    * The instance dataref array must be a valid pointer to a null-terminated
+      array.  That is, if you do not want any datarefs, you must pass a pointer
+      to a one-element array containing a null item.  You cannot pass null for
+      the array itself.
+   }
+   FUNCTION XPLMCreateInstance(
+                                        obj                 : XPLMObjectRef;
+                                        datarefs            : PXPLMString) : XPLMInstanceRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDestroyInstance
+    
+    XPLMDestroyInstance destroys and deallocates your instance; once called,
+    you are still responsible for releasing the OBJ ref.
+    
+    Tip: you can release your OBJ ref after you call XPLMCreateInstance as long
+    as you never use it again; the instance will maintain its own reference to
+    the OBJ and the object OBJ be deallocated when the instance is destroyed.
+   }
+   PROCEDURE XPLMDestroyInstance(
+                                        instance            : XPLMInstanceRef);
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * Instance Manipulation
+ ___________________________________________________________________________}
+
+   {
+    XPLMInstanceSetPosition
+    
+    Updates both the position of the instance and all datarefs you registered
+    for it.  Call this from a flight loop callback or UI callback.
+    
+    __DO_NOT__ call XPLMInstanceSetPosition from a drawing callback; the whole
+    point of instancing is that you do not need any drawing callbacks. Setting
+    instance data from a drawing callback may have undefined consequences, and
+    the drawing callback hurts FPS unnecessarily.  
+    
+    The memory pointed to by the data pointer must be large enough to hold one
+    float for every dataref you have registered, and must contain valid
+    floating point data.
+    
+    BUG: before X-Plane 11.50, if you have no dataref registered, you must
+    still pass a valid pointer for data and not null.
+   }
+   PROCEDURE XPLMInstanceSetPosition(
+                                        instance            : XPLMInstanceRef;
+                                        new_position        : PXPLMDrawInfo_t;
+                                        data                : PSingle);
+    cdecl; external XPLM_DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMMap.pas b/SDK/Delphi/XPLM/XPLMMap.pas
new file mode 100644
index 0000000..abd374e
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMMap.pas
@@ -0,0 +1,608 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMMap;
+INTERFACE
+{
+   This API allows you to create new layers within X-Plane maps. Your layers
+   can draw arbitrary OpenGL, but they conveniently also have access to
+   X-Plane's built-in icon and label drawing functions.
+   
+   As of X-Plane 11, map drawing happens in three stages:
+   
+   1. backgrounds and "fill",
+   2. icons, and
+   3. labels.
+   
+   Thus, all background drawing gets layered beneath all icons, which likewise
+   get layered beneath all labels. Within each stage, the map obeys a
+   consistent layer ordering, such that "fill" layers (layers that cover a
+   large amount of map area, like the terrain and clouds) appear beneath
+   "markings" layers (like airport icons). This ensures that layers with fine
+   details don't get obscured by layers with larger details.
+   
+   The XPLM map API reflects both aspects of this draw layering: you can
+   register a layer as providing either markings or fill, and X-Plane will
+   draw your fill layers beneath your markings layers (regardless of
+   registration order). Likewise, you are guaranteed that your layer's icons
+   (added from within an icon callback) will go above your layer's OpenGL
+   drawing, and your labels will go above your icons.
+   
+   The XPLM guarantees that all plugin-created fill layers go on top of all
+   native X-Plane fill layers, and all plugin-created markings layers go on
+   top of all X-Plane markings layers (with the exception of the aircraft
+   icons). It also guarantees that the draw order of your own plugin's layers
+   will be consistent. But, for layers created by different plugins, the only
+   guarantee is that we will draw all of one plugin's layers of each type
+   (fill, then markings), then all of the others'; we don't guarantee which
+   plugin's fill and markings layers go on top of the other's.
+   
+   As of X-Plane 11, maps use true cartographic projections for their drawing,
+   and different maps may use different projections. For that reason, all
+   drawing calls include an opaque handle for the projection you should use to
+   do the drawing. Any time you would draw at a particular latitude/longitude,
+   you'll need to ask the projection to translate that position into "map
+   coordinates." (Note that the projection is guaranteed not to change between
+   calls to your prepare-cache hook, so if you cache your map coordinates
+   ahead of time, there's no need to re-project them when you actually draw.)
+   
+   In addition to mapping normal latitude/longitude locations into map
+   coordinates, the projection APIs also let you know the current heading for
+   north. (Since X-Plane 11 maps can rotate to match the heading of the user's
+   aircraft, it's not safe to assume that north is at zero degrees rotation.)
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * DRAWING CALLBACKS
+ ___________________________________________________________________________}
+{
+   When you create a new map layer (using XPLMCreateMapLayer), you can provide
+   any or all of these callbacks. They allow you to insert your own OpenGL
+   drawing, text labels, and icons into the X-Plane map at the appropriate
+   places, allowing your layer to behave as similarly to X-Plane's built-in
+   layers as possible.
+}
+
+
+TYPE
+   {
+    XPLMMapLayerID
+    
+    This is an opaque handle for a plugin-created map layer. Pass it to the map
+    drawing APIs from an appropriate callback to draw in the layer you created.
+   }
+   XPLMMapLayerID = pointer;
+   PXPLMMapLayerID = ^XPLMMapLayerID;
+
+   {
+    XPLMMapProjectionID
+    
+    This is an opaque handle for a map projection. Pass it to the projection
+    APIs to translate between map coordinates and latitude/longitudes.
+   }
+   XPLMMapProjectionID = pointer;
+   PXPLMMapProjectionID = ^XPLMMapProjectionID;
+
+   {
+    XPLMMapStyle
+    
+    Indicates the visual style being drawn by the map. In X-Plane, the user can
+    choose between a number of map types, and different map types may have use
+    a different visual representation for the same elements (for instance, the
+    visual style of the terrain layer changes drastically between the VFR and
+    IFR layers), or certain layers may be disabled entirely in some map types
+    (e.g., localizers are only visible in the IFR low-enroute style).
+   }
+   XPLMMapStyle = (
+      xplm_MapStyle_VFR_Sectional              = 0
+ 
+     ,xplm_MapStyle_IFR_LowEnroute             = 1
+ 
+     ,xplm_MapStyle_IFR_HighEnroute            = 2
+ 
+   );
+   PXPLMMapStyle = ^XPLMMapStyle;
+
+   {
+    XPLMMapDrawingCallback_f
+    
+    This is the OpenGL map drawing callback for plugin-created map layers. You
+    can perform arbitrary OpenGL drawing from this callback, with one
+    exception: changes to the Z-buffer are not permitted, and will result in
+    map drawing errors.
+    
+    All drawing done from within this callback appears beneath all built-in
+    X-Plane icons and labels, but above the built-in "fill" layers (layers
+    providing major details, like terrain and water). Note, however, that the
+    relative ordering between the drawing callbacks of different plugins is not
+    guaranteed.
+   }
+     XPLMMapDrawingCallback_f = PROCEDURE(
+                                    inLayer             : XPLMMapLayerID;
+                                    inMapBoundsLeftTopRightBottom: PSingle;
+                                    zoomRatio           : Single;
+                                    mapUnitsPerUserInterfaceUnit: Single;
+                                    mapStyle            : XPLMMapStyle;
+                                    projection          : XPLMMapProjectionID;
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMMapIconDrawingCallback_f
+    
+    This is the icon drawing callback that enables plugin-created map layers to
+    draw icons using X-Plane's built-in icon drawing functionality. You can
+    request an arbitrary number of PNG icons to be drawn via
+    XPLMDrawMapIconFromSheet() from within this callback, but you may not
+    perform any OpenGL drawing here.
+    
+    Icons enqueued by this function will appear above all OpenGL drawing
+    (performed by your optional XPLMMapDrawingCallback_f), and above all
+    built-in X-Plane map icons of the same layer type ("fill" or "markings," as
+    determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
+    however, that the relative ordering between the drawing callbacks of
+    different plugins is not guaranteed.
+   }
+     XPLMMapIconDrawingCallback_f = PROCEDURE(
+                                    inLayer             : XPLMMapLayerID;
+                                    inMapBoundsLeftTopRightBottom: PSingle;
+                                    zoomRatio           : Single;
+                                    mapUnitsPerUserInterfaceUnit: Single;
+                                    mapStyle            : XPLMMapStyle;
+                                    projection          : XPLMMapProjectionID;
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMMapLabelDrawingCallback_f
+    
+    This is the label drawing callback that enables plugin-created map layers
+    to draw text labels using X-Plane's built-in labeling functionality. You
+    can request an arbitrary number of text labels to be drawn via
+    XPLMDrawMapLabel() from within this callback, but you may not perform any
+    OpenGL drawing here.
+    
+    Labels enqueued by this function will appear above all OpenGL drawing
+    (performed by your optional XPLMMapDrawingCallback_f), and above all
+    built-in map icons and labels of the same layer type ("fill" or "markings,"
+    as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
+    however, that the relative ordering between the drawing callbacks of
+    different plugins is not guaranteed.
+   }
+     XPLMMapLabelDrawingCallback_f = PROCEDURE(
+                                    inLayer             : XPLMMapLayerID;
+                                    inMapBoundsLeftTopRightBottom: PSingle;
+                                    zoomRatio           : Single;
+                                    mapUnitsPerUserInterfaceUnit: Single;
+                                    mapStyle            : XPLMMapStyle;
+                                    projection          : XPLMMapProjectionID;
+                                    inRefcon            : pointer); cdecl;
+
+{$ENDIF XPLM300}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * LAYER MANAGEMENT CALLBACKS
+ ___________________________________________________________________________}
+{
+   These are various "bookkeeping" callbacks that your map layer can receive
+   (if you provide the callback in your XPLMCreateMapLayer_t). They allow you
+   to manage the lifecycle of your layer, as well as cache any
+   computationally-intensive preparation you might need for drawing.
+}
+
+
+   {
+    XPLMMapPrepareCacheCallback_f
+    
+    A callback used to allow you to cache whatever information your layer needs
+    to draw in the current map area.
+    
+    This is called each time the map's total bounds change. This is typically
+    triggered by new DSFs being loaded, such that X-Plane discards old,
+    now-distant DSFs and pulls in new ones. At that point, the available bounds
+    of the map also change to match the new DSF area.
+    
+    By caching just the information you need to draw in this area, your future
+    draw calls can be made faster, since you'll be able to simply "splat" your
+    precomputed information each frame.
+    
+    We guarantee that the map projection will not change between successive
+    prepare cache calls, nor will any draw call give you bounds outside these
+    total map bounds. So, if you cache the projected map coordinates of all the
+    items you might want to draw in the total map area, you can be guaranteed
+    that no draw call will be asked to do any new work.
+   }
+TYPE
+     XPLMMapPrepareCacheCallback_f = PROCEDURE(
+                                    inLayer             : XPLMMapLayerID;
+                                    inTotalMapBoundsLeftTopRightBottom: PSingle;
+                                    projection          : XPLMMapProjectionID;
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMMapWillBeDeletedCallback_f
+    
+    Called just before your map layer gets deleted. Because SDK-created map
+    layers have the same lifetime as the X-Plane map that contains them, if the
+    map gets unloaded from memory, your layer will too.
+   }
+     XPLMMapWillBeDeletedCallback_f = PROCEDURE(
+                                    inLayer             : XPLMMapLayerID;
+                                    inRefcon            : pointer); cdecl;
+
+{$ENDIF XPLM300}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * MAP LAYER CREATION AND DESTRUCTION
+ ___________________________________________________________________________}
+{
+   Enables the creation of new map layers. Layers are created for a particular
+   instance of the X-Plane map. For instance, if you want your layer to appear
+   in both the normal map interface and the Instructor Operator Station (IOS),
+   you would need two separate calls to XPLMCreateMapLayer(), with two
+   different values for your XPLMCreateMapLayer_t::layer_name.
+   
+   Your layer's lifetime will be determined by the lifetime of the map it is
+   created in. If the map is destroyed (on the X-Plane side), your layer will
+   be too, and you'll receive a callback to your
+   XPLMMapWillBeDeletedCallback_f.
+}
+
+
+   {
+    XPLMMapLayerType
+    
+    Indicates the type of map layer you are creating. Fill layers will always
+    be drawn beneath markings layers.
+   }
+TYPE
+   XPLMMapLayerType = (
+     { A layer that draws "fill" graphics, like weather patterns, terrain, etc.   }
+     { Fill layers frequently cover a large portion of the visible map area.      }
+      xplm_MapLayer_Fill                       = 0
+ 
+     { A layer that provides markings for particular map features, like NAVAIDs,  }
+     { airports, etc. Even dense markings layers cover a small portion of the     }
+     { total map area.                                                            }
+     ,xplm_MapLayer_Markings                   = 1
+ 
+   );
+   PXPLMMapLayerType = ^XPLMMapLayerType;
+
+CONST
+    { Globally unique identifier for X-Plane's Map window, used as the           }
+    { mapToCreateLayerIn parameter in XPLMCreateMapLayer_t                       }
+   XPLM_MAP_USER_INTERFACE = "XPLM_MAP_USER_INTERFACE";
+
+    { Globally unique identifier for X-Plane's Instructor Operator Station       }
+    { window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t   }
+   XPLM_MAP_IOS         = "XPLM_MAP_IOS";
+
+   {
+    XPLMCreateMapLayer_t
+    
+    This structure defines all of the parameters used to create a map layer
+    using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs
+    to include more features.  Always set the structSize member to the size of
+    your struct in bytes!
+    
+    Each layer must be associated with exactly one map instance in X-Plane.
+    That map, and that map alone, will call your callbacks. Likewise, when that
+    map is deleted, your layer will be as well.
+   }
+TYPE
+   XPLMCreateMapLayer_t = RECORD
+     { Used to inform XPLMCreateMapLayer() of the SDK version you compiled        }
+     { against; should always be set to sizeof(XPLMCreateMapLayer_t)              }
+     structSize               : Integer;
+     { Globally unique string identifying the map you want this layer to appear   }
+     { in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or    }
+     { XPLM_MAP_IOS                                                               }
+     mapToCreateLayerIn       : XPLMString;
+     { The type of layer you are creating, used to determine draw order (all      }
+     { plugin-created markings layers are drawn above all plugin-created fill     }
+     { layers)                                                                    }
+     layerType                : XPLMMapLayerType;
+     { Optional callback to inform you this layer is being deleted (due to its    }
+     { owning map being destroyed)                                                }
+     willBeDeletedCallback    : XPLMMapWillBeDeletedCallback_f;
+     { Optional callback you want to use to prepare your draw cache when the map  }
+     { bounds change (set to NULL if you don't want this callback)                }
+     prepCacheCallback        : XPLMMapPrepareCacheCallback_f;
+     { Optional callback you want to use for arbitrary OpenGL drawing, which goes }
+     { beneath all icons in the map's layering system (set to NULL if you don't   }
+     { want this callback)                                                        }
+     drawCallback             : XPLMMapDrawingCallback_f;
+     { Optional callback you want to use for drawing icons, which go above all    }
+     { built-in X-Plane icons (except the aircraft) in the map's layering system  }
+     { (set to NULL if you don't want this callback)                              }
+     iconCallback             : XPLMMapIconDrawingCallback_f;
+     { Optional callback you want to use for drawing map labels, which go above   }
+     { all built-in X-Plane icons and labels (except those of aircraft) in the    }
+     { map's layering system (set to NULL if you don't want this callback)        }
+     labelCallback            : XPLMMapLabelDrawingCallback_f;
+     { True if you want a checkbox to be created in the map UI to toggle this     }
+     { layer on and off; false if the layer should simply always be enabled       }
+     showUiToggle             : Integer;
+     { Short label to use for this layer in the user interface                    }
+     layerName                : XPLMString;
+     { A reference to arbitrary data that will be passed to your callbacks        }
+     refcon                   : pointer;
+   END;
+   PXPLMCreateMapLayer_t = ^XPLMCreateMapLayer_t;
+
+   {
+    XPLMCreateMapLayer
+    
+    This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t
+    structure with all of the fields defined.  You must set the structSize of
+    the structure to the size of the actual structure you used.
+    
+    Returns NULL if the layer creation failed. This happens most frequently
+    because the map you specified in your
+    XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if
+    XPLMMapExists() returns 0 for the specified map). You can use
+    XPLMRegisterMapCreationHook() to get a notification each time a new map is
+    opened in X-Plane, at which time you can create layers in it.
+   }
+   FUNCTION XPLMCreateMapLayer(
+                                        inParams            : PXPLMCreateMapLayer_t) : XPLMMapLayerID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDestroyMapLayer
+    
+    Destroys a map layer you created (calling your
+    XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion
+    took place.
+   }
+   FUNCTION XPLMDestroyMapLayer(
+                                        inLayer             : XPLMMapLayerID) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMMapCreatedCallback_f
+    
+    A callback to notify your plugin that a new map has been created in
+    X-Plane. This is the best time to add a custom map layer using
+    XPLMCreateMapLayer().
+    
+    No OpenGL drawing is permitted within this callback.
+   }
+TYPE
+     XPLMMapCreatedCallback_f = PROCEDURE(
+                                    mapIdentifier       : XPLMString;
+                                    refcon              : pointer); cdecl;
+
+   {
+    XPLMRegisterMapCreationHook
+    
+    Registers your callback to receive a notification each time a new map is
+    constructed in X-Plane. This callback is the best time to add your custom
+    map layer using XPLMCreateMapLayer().
+    
+    Note that you will not be notified about any maps that already exist---you
+    can use XPLMMapExists() to check for maps that were created previously.
+   }
+   PROCEDURE XPLMRegisterMapCreationHook(
+                                        callback            : XPLMMapCreatedCallback_f;
+                                        refcon              : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMMapExists
+    
+    Returns 1 if the map with the specified identifier already exists in
+    X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying
+    that your layer should be added to that map.
+   }
+   FUNCTION XPLMMapExists(
+                                        mapIdentifier       : XPLMString) : Integer;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM300}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * MAP DRAWING
+ ___________________________________________________________________________}
+{
+   These APIs are only valid from within a map drawing callback (one of
+   XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing
+   callbacks are registered when you create a new map layer as part of your
+   XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map
+   drawing functionality for icons and labels, so that you get a consistent
+   style with the rest of the X-Plane map.
+   
+   Note that the X-Plane 11 map introduces a strict ordering: layers of type
+   xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers.
+   Likewise, all OpenGL drawing (performed in your layer's
+   XPLMMapDrawingCallback_f) will appear beneath any icons and labels you
+   draw.
+}
+
+
+   {
+    XPLMMapOrientation
+    
+    Indicates whether a map element should be match its rotation to the map
+    itself, or to the user interface. For instance, the map itself may be
+    rotated such that "up" matches the user's aircraft, but you may want to
+    draw a text label such that it is always rotated zero degrees relative to
+    the user's perspective. In that case, you would have it draw with UI
+    orientation.
+   }
+TYPE
+   XPLMMapOrientation = (
+     { Orient such that a 0 degree rotation matches the map's north               }
+      xplm_MapOrientation_Map                  = 0
+ 
+     { Orient such that a 0 degree rotation is "up" relative to the user interface}
+     ,xplm_MapOrientation_UI                   = 1
+ 
+   );
+   PXPLMMapOrientation = ^XPLMMapOrientation;
+
+   {
+    XPLMDrawMapIconFromSheet
+    
+    Enables plugin-created map layers to draw PNG icons using X-Plane's
+    built-in icon drawing functionality. Only valid from within an
+    XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons
+    to be drawn from within your callback).
+    
+    X-Plane will automatically manage the memory for your texture so that it
+    only has to be loaded from disk once as long as you continue drawing it
+    per-frame. (When you stop drawing it, the memory may purged in a "garbage
+    collection" pass, require a load from disk in the future.)
+    
+    Instead of having X-Plane draw a full PNG, this method allows you to use UV
+    coordinates to request a portion of the image to be drawn. This allows you
+    to use a single texture load (of an icon sheet, for example) to draw many
+    icons. Doing so is much more efficient than drawing a dozen different small
+    PNGs.
+    
+    The UV coordinates used here treat the texture you load as being comprised
+    of a number of identically sized "cells". You specify the width and height
+    in cells (ds and dt, respectively), as well as the coordinates within the
+    cell grid for the sub-image you'd like to draw.
+    
+    Note that you can use different ds and dt values in subsequent calls with
+    the same texture sheet. This enables you to use icons of different sizes in
+    the same sheet if you arrange them properly in the PNG.
+    
+    This function is only valid from within an XPLMIconDrawingCallback_t (but
+    you can request an arbitrary number of icons to be drawn from within your
+    callback).
+   }
+   PROCEDURE XPLMDrawMapIconFromSheet(
+                                        layer               : XPLMMapLayerID;
+                                        inPngPath           : XPLMString;
+                                        s                   : Integer;
+                                        t                   : Integer;
+                                        ds                  : Integer;
+                                        dt                  : Integer;
+                                        mapX                : Single;
+                                        mapY                : Single;
+                                        orientation         : XPLMMapOrientation;
+                                        rotationDegrees     : Single;
+                                        mapWidth            : Single);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDrawMapLabel
+    
+    Enables plugin-created map layers to draw text labels using X-Plane's
+    built-in labeling functionality. Only valid from within an
+    XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of
+    text labels to be drawn from within your callback).
+   }
+   PROCEDURE XPLMDrawMapLabel(
+                                        layer               : XPLMMapLayerID;
+                                        inText              : XPLMString;
+                                        mapX                : Single;
+                                        mapY                : Single;
+                                        orientation         : XPLMMapOrientation;
+                                        rotationDegrees     : Single);
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM300}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * MAP PROJECTIONS
+ ___________________________________________________________________________}
+{
+   As of X-Plane 11, the map draws using true cartographic projections, and
+   different maps may use different projections. Thus, to draw at a particular
+   latitude and longitude, you must first transform your real-world
+   coordinates into map coordinates.
+   
+   The map projection is also responsible for giving you the current scale of
+   the map. That is, the projection can tell you how many map units correspond
+   to 1 meter at a given point.
+   
+   Finally, the map projection can give you the current rotation of the map.
+   Since X-Plane 11 maps can rotate to match the heading of the aircraft, the
+   map's rotation can potentially change every frame.
+}
+
+
+   {
+    XPLMMapProject
+    
+    Projects a latitude/longitude into map coordinates. This is the inverse of
+    XPLMMapUnproject().
+    
+    Only valid from within a map layer callback (one of
+    XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+    XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+   }
+   PROCEDURE XPLMMapProject(
+                                        projection          : XPLMMapProjectionID;
+                                        latitude            : Real;
+                                        longitude           : Real;
+                                        outX                : PSingle;
+                                        outY                : PSingle);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMMapUnproject
+    
+    Transforms map coordinates back into a latitude and longitude. This is the
+    inverse of XPLMMapProject().
+    
+    Only valid from within a map layer callback (one of
+    XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+    XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+   }
+   PROCEDURE XPLMMapUnproject(
+                                        projection          : XPLMMapProjectionID;
+                                        mapX                : Single;
+                                        mapY                : Single;
+                                        outLatitude         : PReal;
+                                        outLongitude        : PReal);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMMapScaleMeter
+    
+    Returns the number of map units that correspond to a distance of one meter
+    at a given set of map coordinates.
+    
+    Only valid from within a map layer callback (one of
+    XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+    XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+   }
+   FUNCTION XPLMMapScaleMeter(
+                                        projection          : XPLMMapProjectionID;
+                                        mapX                : Single;
+                                        mapY                : Single) : Single;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMMapGetNorthHeading
+    
+    Returns the heading (in degrees clockwise) from the positive Y axis in the
+    cartesian mapping coordinate system to true north at the point passed in. 
+    You can use it as a clockwise rotational offset to align icons and other
+    2-d drawing with true north on the map, compensating for rotations in the
+    map due to projection.
+    
+    Only valid from within a map layer callback (one of
+    XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
+    XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)
+   }
+   FUNCTION XPLMMapGetNorthHeading(
+                                        projection          : XPLMMapProjectionID;
+                                        mapX                : Single;
+                                        mapY                : Single) : Single;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM300}
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMMenus.pas b/SDK/Delphi/XPLM/XPLMMenus.pas
new file mode 100644
index 0000000..64cdda5
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMMenus.pas
@@ -0,0 +1,277 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMMenus;
+INTERFACE
+{
+   Plug-ins can create menus in the menu bar of X-Plane.  This is done by
+   creating a menu and then creating items.  Menus are referred to by an
+   opaque ID.  Items are referred to by (zero-based) index number.
+   
+   Menus are "sandboxed" between plugins - no plugin can access the menus of
+   any other plugin. Furthermore, all menu indices are relative to your
+   plugin's menus only; if your plugin creates two sub-menus in the Plugins
+   menu at different times, it doesn't matter how many other plugins also
+   create sub-menus of Plugins in the intervening time: your sub-menus will be
+   given menu indices 0 and 1. (The SDK does some work in the back-end to
+   filter out menus that are irrelevant to your plugin in order to deliver
+   this consistency for each plugin.)
+   
+   When you create a menu item, you specify how we should handle clicks on
+   that menu item. You can either have the XPLM trigger a callback (the
+   XPLMMenuHandler_f associated with the menu that contains the item), or you
+   can simply have a command be triggered (with no associated call to your
+   menu handler). The advantage of the latter method is that X-Plane will
+   display any keyboard shortcuts associated with the command. (In contrast,
+   there are no keyboard shortcuts associated with menu handler callbacks with
+   specific parameters.)
+   
+   Menu text in X-Plane is UTF8; X-Plane's character set covers latin, greek
+   and cyrillic characters, Katakana, as well as some Japanese symbols. Some
+   APIs have a inDeprecatedAndIgnored parameter that used to select a
+   character set; since X-Plane 9 all localization is done via UTF-8 only.
+}
+
+USES
+    XPLMDefs, XPLMUtilities;
+   {$A4}
+{___________________________________________________________________________
+ * XPLM MENUS
+ ___________________________________________________________________________}
+
+   {
+    XPLMMenuCheck
+    
+    These enumerations define the various 'check' states for an X-Plane menu. 
+    'Checking' in X-Plane actually appears as a light which may or may not be
+    lit.  So there are three possible states.
+   }
+TYPE
+   XPLMMenuCheck = (
+     { There is no symbol to the left of the menu item.                           }
+      xplm_Menu_NoCheck                        = 0
+ 
+     { The menu has a mark next to it that is unmarked (not lit).                 }
+     ,xplm_Menu_Unchecked                      = 1
+ 
+     { The menu has a mark next to it that is checked (lit).                      }
+     ,xplm_Menu_Checked                        = 2
+ 
+   );
+   PXPLMMenuCheck = ^XPLMMenuCheck;
+
+   {
+    XPLMMenuID
+    
+    This is a unique ID for each menu you create.
+   }
+   XPLMMenuID = pointer;
+   PXPLMMenuID = ^XPLMMenuID;
+
+   {
+    XPLMMenuHandler_f
+    
+    A menu handler function takes two reference pointers, one for the menu
+    (specified when the menu was created) and one for the item (specified when
+    the item was created).
+   }
+     XPLMMenuHandler_f = PROCEDURE(
+                                    inMenuRef           : pointer;
+                                    inItemRef           : pointer); cdecl;
+
+   {
+    XPLMFindPluginsMenu
+    
+    This function returns the ID of the plug-ins menu, which is created for you
+    at startup.
+   }
+   FUNCTION XPLMFindPluginsMenu: XPLMMenuID;
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMFindAircraftMenu
+    
+    This function returns the ID of the menu for the currently-loaded aircraft,
+    used for showing aircraft-specific commands.
+    
+    The aircraft menu is created by X-Plane at startup, but it remains hidden
+    until it is populated via XPLMAppendMenuItem() or
+    XPLMAppendMenuItemWithCommand().
+    
+    Only plugins loaded with the user's current aircraft are allowed to access
+    the aircraft menu. For all other plugins, this will return NULL, and any
+    attempts to add menu items to it will fail.
+   }
+   FUNCTION XPLMFindAircraftMenu: XPLMMenuID;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+   {
+    XPLMCreateMenu
+    
+    This function creates a new menu and returns its ID.  It returns NULL if
+    the menu cannot be created.  Pass in a parent menu ID and an item index to
+    create a submenu, or NULL for the parent menu to put the menu in the menu
+    bar.  The menu's name is only used if the menu is in the menubar.  You also
+    pass a handler function and a menu reference value. Pass NULL for the
+    handler if you do not need callbacks from the menu (for example, if it only
+    contains submenus).
+    
+    Important: you must pass a valid, non-empty menu title even if the menu is
+    a submenu where the title is not visible.
+   }
+   FUNCTION XPLMCreateMenu(
+                                        inName              : XPLMString;
+                                        inParentMenu        : XPLMMenuID;
+                                        inParentItem        : Integer;
+                                        inHandler           : XPLMMenuHandler_f;
+                                        inMenuRef           : pointer) : XPLMMenuID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDestroyMenu
+    
+    This function destroys a menu that you have created.  Use this to remove a
+    submenu if necessary.  (Normally this function will not be necessary.)
+   }
+   PROCEDURE XPLMDestroyMenu(
+                                        inMenuID            : XPLMMenuID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMClearAllMenuItems
+    
+    This function removes all menu items from a menu, allowing you to rebuild
+    it.  Use this function if you need to change the number of items on a menu.
+   }
+   PROCEDURE XPLMClearAllMenuItems(
+                                        inMenuID            : XPLMMenuID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMAppendMenuItem
+    
+    This routine appends a new menu item to the bottom of a menu and returns
+    its index. Pass in the menu to add the item to, the items name, and a void
+    * ref for this item.
+    
+    Returns a negative index if the append failed (due to an invalid parent
+    menu argument).
+    
+    Note that all menu indices returned are relative to your plugin's menus
+    only; if your plugin creates two sub-menus in the Plugins menu at different
+    times, it doesn't matter how many other plugins also create sub-menus of
+    Plugins in the intervening time: your sub-menus will be given menu indices
+    0 and 1. (The SDK does some work in the back-end to filter out menus that
+    are irrelevant to your plugin in order to deliver this consistency for each
+    plugin.)
+   }
+   FUNCTION XPLMAppendMenuItem(
+                                        inMenu              : XPLMMenuID;
+                                        inItemName          : XPLMString;
+                                        inItemRef           : pointer;
+                                        inDeprecatedAndIgnored: Integer) : Integer;
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM300}
+   {
+    XPLMAppendMenuItemWithCommand
+    
+    Like XPLMAppendMenuItem(), but instead of the new menu item triggering the
+    XPLMMenuHandler_f of the containiner menu, it will simply execute the
+    command you pass in. Using a command for your menu item allows the user to
+    bind a keyboard shortcut to the command and see that shortcut represented
+    in the menu.
+    
+    Returns a negative index if the append failed (due to an invalid parent
+    menu argument).
+    
+    Like XPLMAppendMenuItem(), all menu indices are relative to your plugin's
+    menus only.
+   }
+   FUNCTION XPLMAppendMenuItemWithCommand(
+                                        inMenu              : XPLMMenuID;
+                                        inItemName          : XPLMString;
+                                        inCommandToExecute  : XPLMCommandRef) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+
+   {
+    XPLMAppendMenuSeparator
+    
+    This routine adds a separator to the end of a menu.
+    
+    Returns a negative index if the append failed (due to an invalid parent
+    menu argument).
+   }
+   PROCEDURE XPLMAppendMenuSeparator(
+                                        inMenu              : XPLMMenuID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetMenuItemName
+    
+    This routine changes the name of an existing menu item.  Pass in the menu
+    ID and the index of the menu item.
+   }
+   PROCEDURE XPLMSetMenuItemName(
+                                        inMenu              : XPLMMenuID;
+                                        inIndex             : Integer;
+                                        inItemName          : XPLMString;
+                                        inDeprecatedAndIgnored: Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCheckMenuItem
+    
+    Set whether a menu item is checked.  Pass in the menu ID and item index.
+   }
+   PROCEDURE XPLMCheckMenuItem(
+                                        inMenu              : XPLMMenuID;
+                                        index               : Integer;
+                                        inCheck             : XPLMMenuCheck);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCheckMenuItemState
+    
+    This routine returns whether a menu item is checked or not. A menu item's
+    check mark may be on or off, or a menu may not have an icon at all.
+   }
+   PROCEDURE XPLMCheckMenuItemState(
+                                        inMenu              : XPLMMenuID;
+                                        index               : Integer;
+                                        outCheck            : PXPLMMenuCheck);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMEnableMenuItem
+    
+    Sets whether this menu item is enabled.  Items start out enabled.
+   }
+   PROCEDURE XPLMEnableMenuItem(
+                                        inMenu              : XPLMMenuID;
+                                        index               : Integer;
+                                        enabled             : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM210}
+   {
+    XPLMRemoveMenuItem
+    
+    Removes one item from a menu.  Note that all menu items below are moved up
+    one; your plugin must track the change in index numbers.
+   }
+   PROCEDURE XPLMRemoveMenuItem(
+                                        inMenu              : XPLMMenuID;
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM210}
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMNavigation.pas b/SDK/Delphi/XPLM/XPLMNavigation.pas
new file mode 100644
index 0000000..d969507
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMNavigation.pas
@@ -0,0 +1,591 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMNavigation;
+INTERFACE
+{
+   The XPLM Navigation APIs give you some access to the navigation databases
+   inside X-Plane.  X-Plane stores all navigation information in RAM, so by
+   using these APIs you can gain access to most information without having to
+   go to disk or parse the files yourself.
+   
+   You can also use this API to program the FMS.  You must use the navigation
+   APIs to find the nav-aids you want to program into the FMS, since the FMS
+   is powered internally by X-Plane's navigation database.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * NAVIGATION DATABASE ACCESS
+ ___________________________________________________________________________}
+
+   {
+    XPLMNavType
+    
+    These enumerations define the different types of navaids.  They are each
+    defined with a separate bit so that they may be bit-wise added together to
+    form sets of nav-aid types.
+    
+    NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the
+    FMS. It will not exist in the database, and cannot be programmed into the
+    FMS. Querying the FMS for navaids will return it.  Use
+    XPLMSetFMSEntryLatLon to set a lat/lon waypoint.
+   }
+TYPE
+   XPLMNavType = (
+      xplm_Nav_Unknown                         = 0
+ 
+     ,xplm_Nav_Airport                         = 1
+ 
+     ,xplm_Nav_NDB                             = 2
+ 
+     ,xplm_Nav_VOR                             = 4
+ 
+     ,xplm_Nav_ILS                             = 8
+ 
+     ,xplm_Nav_Localizer                       = 16
+ 
+     ,xplm_Nav_GlideSlope                      = 32
+ 
+     ,xplm_Nav_OuterMarker                     = 64
+ 
+     ,xplm_Nav_MiddleMarker                    = 128
+ 
+     ,xplm_Nav_InnerMarker                     = 256
+ 
+     ,xplm_Nav_Fix                             = 512
+ 
+     ,xplm_Nav_DME                             = 1024
+ 
+     ,xplm_Nav_LatLon                          = 2048
+ 
+     ,xplm_Nav_TACAN                           = 4096
+ 
+   );
+   PXPLMNavType = ^XPLMNavType;
+
+   {
+    XPLMNavRef
+    
+    XPLMNavRef is an iterator into the navigation database.  The navigation
+    database is essentially an array, but it is not necessarily densely
+    populated. The only assumption you can safely make is that like-typed
+    nav-aids are grouped together.
+    
+    Use XPLMNavRef to refer to a nav-aid.
+    
+    XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when
+    the iterator must be invalid.
+   }
+   XPLMNavRef = Integer;
+   PXPLMNavRef = ^XPLMNavRef;
+
+CONST
+   XPLM_NAV_NOT_FOUND   = -1;
+
+   {
+    XPLMGetFirstNavAid
+    
+    This returns the very first navaid in the database.  Use this to traverse
+    the entire database.  Returns XPLM_NAV_NOT_FOUND if the nav database is
+    empty.
+   }
+   FUNCTION XPLMGetFirstNavAid: XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetNextNavAid
+    
+    Given a valid navaid ref, this routine returns the next navaid.  It returns
+    XPLM_NAV_NOT_FOUND if the navaid passed in was invalid or if the navaid
+    passed in was the last one in the database.  Use this routine to iterate
+    across all like-typed navaids or the entire database.
+   }
+   FUNCTION XPLMGetNextNavAid(
+                                        inNavAidRef         : XPLMNavRef) : XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMFindFirstNavAidOfType
+    
+    This routine returns the ref of the first navaid of the given type in the
+    database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the
+    database.  You must pass exactly one navaid type to this routine.
+   }
+   FUNCTION XPLMFindFirstNavAidOfType(
+                                        inType              : XPLMNavType) : XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMFindLastNavAidOfType
+    
+    This routine returns the ref of the last navaid of the given type in the
+    database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the
+    database.  You must pass exactly one navaid type to this routine.
+   }
+   FUNCTION XPLMFindLastNavAidOfType(
+                                        inType              : XPLMNavType) : XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMFindNavAid
+    
+    This routine provides a number of searching capabilities for the nav
+    database. XPLMFindNavAid will search through every navaid whose type is
+    within inType (multiple types may be added together) and return any navaids
+    found based on the following rules:
+    
+    * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will
+      be returned, otherwise the last navaid found will be returned.
+    
+    * If inFrequency is not NULL, then any navaids considered must match this
+      frequency.  Note that this will screen out radio beacons that do not have
+      frequency data published (like inner markers) but not fixes and airports.
+    
+    * If inNameFragment is not NULL, only navaids that contain the fragment in
+      their name will be returned.
+    
+    * If inIDFragment is not NULL, only navaids that contain the fragment in
+      their IDs will be returned.
+    
+    This routine provides a simple way to do a number of useful searches:
+    * Find the nearest navaid on this frequency.
+    * Find the nearest airport.
+    * Find the VOR whose ID is "BOS".
+    * Find the nearest airport whose name contains "Chicago".
+   }
+   FUNCTION XPLMFindNavAid(
+                                        inNameFragment      : XPLMString;    { Can be nil }
+                                        inIDFragment        : XPLMString;    { Can be nil }
+                                        inLat               : PSingle;    { Can be nil }
+                                        inLon               : PSingle;    { Can be nil }
+                                        inFrequency         : PInteger;    { Can be nil }
+                                        inType              : XPLMNavType) : XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetNavAidInfo
+    
+    This routine returns information about a navaid.  Any non-null field is
+    filled out with information if it is available.
+    
+    Frequencies are in the nav.dat convention as described in the X-Plane nav
+    database FAQ: NDB frequencies are exact, all others are multiplied by 100.
+    
+    The buffer for IDs should be at least 6 chars and the buffer for names
+    should be at least 41 chars, but since these values are likely to go up, I
+    recommend passing at least 32 chars for IDs and 256 chars for names when
+    possible.
+    
+    The outReg parameter tells if the navaid is within the local "region" of
+    loaded DSFs.  (This information may not be particularly useful to plugins.)
+    The parameter is a single byte value 1 for true or 0 for false, not a C
+    string.
+   }
+   PROCEDURE XPLMGetNavAidInfo(
+                                        inRef               : XPLMNavRef;
+                                        outType             : PXPLMNavType;    { Can be nil }
+                                        outLatitude         : PSingle;    { Can be nil }
+                                        outLongitude        : PSingle;    { Can be nil }
+                                        outHeight           : PSingle;    { Can be nil }
+                                        outFrequency        : PInteger;    { Can be nil }
+                                        outHeading          : PSingle;    { Can be nil }
+                                        outID               : XPLMString;    { Can be nil }
+                                        outName             : XPLMString;    { Can be nil }
+                                        outReg              : XPLMString);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * FLIGHT MANAGEMENT COMPUTER
+ ___________________________________________________________________________}
+{
+   Note: the FMS works based on an array of entries.  Indices into the array
+   are zero-based.  Each entry is a navaid plus an altitude.  The FMS tracks
+   the currently displayed entry and the entry that it is flying to.
+   
+   The FMS must be programmed with contiguous entries, so clearing an entry at
+   the end shortens the effective flight plan.  There is a max of 100
+   waypoints in the flight plan.
+}
+
+
+   {
+    XPLMCountFMSEntries
+    
+    This routine returns the number of entries in the FMS.
+   }
+   FUNCTION XPLMCountFMSEntries: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDisplayedFMSEntry
+    
+    This routine returns the index of the entry the pilot is viewing.
+   }
+   FUNCTION XPLMGetDisplayedFMSEntry: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDestinationFMSEntry
+    
+    This routine returns the index of the entry the FMS is flying to.
+   }
+   FUNCTION XPLMGetDestinationFMSEntry: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDisplayedFMSEntry
+    
+    This routine changes which entry the FMS is showing to the index specified.
+   }
+   PROCEDURE XPLMSetDisplayedFMSEntry(
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetDestinationFMSEntry
+    
+    This routine changes which entry the FMS is flying the aircraft toward. The
+    track is from the n-1'th point to the n'th point. 
+   }
+   PROCEDURE XPLMSetDestinationFMSEntry(
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetFMSEntryInfo
+    
+    This routine returns information about a given FMS entry. If the entry is
+    an airport or navaid, a reference to a nav entry can be returned allowing
+    you to find additional information (such as a frequency, ILS heading, name,
+    etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the
+    information has been looked up asynchronously, so after flightplan changes,
+    it might take up to a second for this field to become populated. The other
+    information is available immediately. For a lat/lon entry, the lat/lon is
+    returned by this routine but the navaid cannot be looked up (and the
+    reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at
+    least 256 chars in length.
+    
+    WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will
+    not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead
+    just remain the value of the variable that you passed the pointer to.
+    Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before
+    passing the pointer to this function.
+   }
+   PROCEDURE XPLMGetFMSEntryInfo(
+                                        inIndex             : Integer;
+                                        outType             : PXPLMNavType;    { Can be nil }
+                                        outID               : XPLMString;    { Can be nil }
+                                        outRef              : PXPLMNavRef;    { Can be nil }
+                                        outAltitude         : PInteger;    { Can be nil }
+                                        outLat              : PSingle;    { Can be nil }
+                                        outLon              : PSingle);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetFMSEntryInfo
+    
+    This routine changes an entry in the FMS to have the destination navaid
+    passed in and the altitude specified.  Use this only for airports, fixes,
+    and radio-beacon navaids.  Currently of radio beacons, the FMS can only
+    support VORs and NDBs. Use the routines below to clear or fly to a lat/lon.
+   }
+   PROCEDURE XPLMSetFMSEntryInfo(
+                                        inIndex             : Integer;
+                                        inRef               : XPLMNavRef;
+                                        inAltitude          : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetFMSEntryLatLon
+    
+    This routine changes the entry in the FMS to a lat/lon entry with the given
+    coordinates.
+   }
+   PROCEDURE XPLMSetFMSEntryLatLon(
+                                        inIndex             : Integer;
+                                        inLat               : Single;
+                                        inLon               : Single;
+                                        inAltitude          : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMClearFMSEntry
+    
+    This routine clears the given entry, potentially shortening the flight
+    plan.
+   }
+   PROCEDURE XPLMClearFMSEntry(
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM410}
+   {
+    XPLMNavFlightPlan
+    
+        These enumerations defines the flightplan you are accesing using the
+        FMSFlightPlan functions. An airplane can have up to two navigation
+        devices (GPS or FMS) and each device can have two flightplans. A GPS
+        has an enroute and an approach flightplan. An FMS has an active and a
+        temporary flightplan. If you are trying to access a flightplan that
+        doesn't exist in your aircraft, e.g. asking a GPS for a temp
+        flightplan, FMSFlighPlan functions have no effect and will return no
+        information.
+   }
+TYPE
+   XPLMNavFlightPlan = (
+      xplm_Fpl_Pilot_Primary                   = 0
+ 
+     ,xplm_Fpl_CoPilot_Primary                 = 1
+ 
+     ,xplm_Fpl_Pilot_Approach                  = 2
+ 
+     ,xplm_Fpl_CoPilot_Approach                = 3
+ 
+     ,xplm_Fpl_Pilot_Temporary                 = 4
+ 
+     ,xplm_Fpl_CoPilot_Temporary               = 5
+ 
+   );
+   PXPLMNavFlightPlan = ^XPLMNavFlightPlan;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMCountFMSFlightPlanEntries
+    
+    This routine returns the number of entries in the FMS.
+   }
+   FUNCTION XPLMCountFMSFlightPlanEntries(
+                                        inFlightPlan        : XPLMNavFlightPlan) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetDisplayedFMSFlightPlanEntry
+    
+    This routine returns the index of the entry the pilot is viewing.
+   }
+   FUNCTION XPLMGetDisplayedFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetDestinationFMSFlightPlanEntry
+    
+    This routine returns the index of the entry the FMS is flying to.
+   }
+   FUNCTION XPLMGetDestinationFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetDisplayedFMSFlightPlanEntry
+    
+    This routine changes which entry the FMS is showing to the index specified.
+   }
+   PROCEDURE XPLMSetDisplayedFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetDestinationFMSFlightPlanEntry
+    
+    This routine changes which entry the FMS is flying the aircraft toward. The
+    track is from the n-1'th point to the n'th point.
+   }
+   PROCEDURE XPLMSetDestinationFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetDirectToFMSFlightPlanEntry
+    
+    This routine changes which entry the FMS is flying the aircraft toward. The
+    track is from the current position of the aircraft directly to the n'th
+    point, ignoring the point before it.
+   }
+   PROCEDURE XPLMSetDirectToFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMGetFMSFlightPlanEntryInfo
+    
+    This routine returns information about a given FMS entry. If the entry is
+    an airport or navaid, a reference to a nav entry can be returned allowing
+    you to find additional information (such as a frequency, ILS heading, name,
+    etc.). Note that this reference can be XPLM_NAV_NOT_FOUND until the
+    information has been looked up asynchronously, so after flightplan changes,
+    it might take up to a second for this field to become populated. The other
+    information is available immediately. For a lat/lon entry, the lat/lon is
+    returned by this routine but the navaid cannot be looked up (and the
+    reference will be XPLM_NAV_NOT_FOUND). FMS name entry buffers should be at
+    least 256 chars in length.
+    
+    WARNING: Due to a bug in X-Plane prior to 11.31, the navaid reference will
+    not be set to XPLM_NAV_NOT_FOUND while no data is available, and instead
+    just remain the value of the variable that you passed the pointer to.
+    Therefore, always initialize the variable to XPLM_NAV_NOT_FOUND before
+    passing the pointer to this function.
+   }
+   PROCEDURE XPLMGetFMSFlightPlanEntryInfo(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer;
+                                        outType             : PXPLMNavType;    { Can be nil }
+                                        outID               : XPLMString;    { Can be nil }
+                                        outRef              : PXPLMNavRef;    { Can be nil }
+                                        outAltitude         : PInteger;    { Can be nil }
+                                        outLat              : PSingle;    { Can be nil }
+                                        outLon              : PSingle);    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetFMSFlightPlanEntryInfo
+    
+    This routine changes an entry in the FMS to have the destination navaid
+    passed in and the altitude specified.  Use this only for airports, fixes,
+    and radio-beacon navaids.  Currently of radio beacons, the FMS can only
+    support VORs, NDBs and TACANs. Use the routines below to clear or fly to a
+    lat/lon.
+   }
+   PROCEDURE XPLMSetFMSFlightPlanEntryInfo(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer;
+                                        inRef               : XPLMNavRef;
+                                        inAltitude          : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetFMSFlightPlanEntryLatLon
+    
+    This routine changes the entry in the FMS to a lat/lon entry with the given
+    coordinates.
+   }
+   PROCEDURE XPLMSetFMSFlightPlanEntryLatLon(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer;
+                                        inLat               : Single;
+                                        inLon               : Single;
+                                        inAltitude          : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSetFMSFlightPlanEntryLatLonWithId
+    
+    This routine changes the entry in the FMS to a lat/lon entry with the given
+    coordinates. You can specify the display ID of the waypoint.
+   }
+   PROCEDURE XPLMSetFMSFlightPlanEntryLatLonWithId(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer;
+                                        inLat               : Single;
+                                        inLon               : Single;
+                                        inAltitude          : Integer;
+                                        inId                : XPLMString;
+                                        inIdLength          : unsigned int);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMClearFMSFlightPlanEntry
+    
+    This routine clears the given entry, potentially shortening the flight
+    plan.
+   }
+   PROCEDURE XPLMClearFMSFlightPlanEntry(
+                                        inFlightPlan        : XPLMNavFlightPlan;
+                                        inIndex             : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMLoadFMSFlightPlan
+    
+    Loads an X-Plane 11 and later formatted flightplan from the buffer into the
+    FMS or GPS, including instrument procedures. Use device index 0 for the
+    pilot-side and device index 1 for the co-pilot side unit.
+   }
+   PROCEDURE XPLMLoadFMSFlightPlan(
+                                        inDevice            : Integer;
+                                        inBuffer            : XPLMString;
+                                        inBufferLen         : unsigned int);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{$IFDEF XPLM410}
+   {
+    XPLMSaveFMSFlightPlan
+    
+    Saves an X-Plane 11 formatted flightplan from the FMS or GPS into a char
+    buffer that you provide. Use device index 0 for the pilot-side and device
+    index 1 for the co-pilot side unit. Provide the length of the buffer you
+    allocated. X-Plane will write a null-terminated string if the full flight
+    plan fits into the buffer. If your buffer is too small, X-Plane will write
+    inBufferLen characters, and the resulting buffer is not null-terminated. 
+    The return value is the number of characters (including null terminator)
+    that X-Plane needed to write the flightplan. If this number is larger than
+    the buffer you provided, the flightplan in the buffer will be incomplete
+    and the buffer not null-terminated.
+   }
+   FUNCTION XPLMSaveFMSFlightPlan(
+                                        inDevice            : Integer;
+                                        inBuffer            : XPLMString;
+                                        inBufferLen         : unsigned int) : unsigned int;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM410}
+
+{___________________________________________________________________________
+ * GPS RECEIVER
+ ___________________________________________________________________________}
+{
+   These APIs let you read data from the GPS unit.
+}
+
+   {
+    XPLMGetGPSDestinationType
+    
+    This routine returns the type of the currently selected GPS destination,
+    one of fix, airport, VOR or NDB.
+   }
+   FUNCTION XPLMGetGPSDestinationType: XPLMNavType;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetGPSDestination
+    
+    This routine returns the current GPS destination.
+   }
+   FUNCTION XPLMGetGPSDestination: XPLMNavRef;
+    cdecl; external XPLM_DLL;
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMPlanes.pas b/SDK/Delphi/XPLM/XPLMPlanes.pas
new file mode 100644
index 0000000..7389921
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMPlanes.pas
@@ -0,0 +1,278 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMPlanes;
+INTERFACE
+{
+   The XPLMPlanes APIs allow you to control the various aircraft in X-Plane,
+   both the user's and the sim's.
+   
+   *Note*: unlike almost all other APIs in the SDK, aircraft paths are _full_
+    file system paths for historical reasons. You'll need to prefix all
+    relative paths with the X-Plane path as accessed via XPLMGetSystemPath.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * USER AIRCRAFT ACCESS
+ ___________________________________________________________________________}
+
+   {
+    XPLMSetUsersAircraft
+    
+    This routine changes the user's aircraft.  Note that this will reinitialize
+    the user to be on the nearest airport's first runway.  Pass in a full path
+    (hard drive and everything including the .acf extension) to the .acf file.
+   }
+   PROCEDURE XPLMSetUsersAircraft(
+                                        inAircraftPath      : XPLMString);
+    cdecl; external XPLM_DLL;
+   {
+    XPLMPlaceUserAtAirport
+    
+    This routine places the user at a given airport.  Specify the airport by
+    its X-Plane airport ID (e.g. 'KBOS').
+   }
+   PROCEDURE XPLMPlaceUserAtAirport(
+                                        inAirportCode       : XPLMString);
+    cdecl; external XPLM_DLL;
+{$IFDEF XPLM300}
+   {
+    XPLMPlaceUserAtLocation
+    
+    Places the user at a specific location after performing any necessary
+    scenery loads.
+    
+    As with in-air starts initiated from the X-Plane user interface, the
+    aircraft will always start with its engines running, regardless of the
+    user's preferences (i.e., regardless of what the dataref
+    `sim/operation/prefs/startup_running` says).
+   }
+   PROCEDURE XPLMPlaceUserAtLocation(
+                                        latitudeDegrees     : Real;
+                                        longitudeDegrees    : Real;
+                                        elevationMetersMSL  : Single;
+                                        headingDegreesTrue  : Single;
+                                        speedMetersPerSecond: Single);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM300}
+{___________________________________________________________________________
+ * GLOBAL AIRCRAFT ACCESS
+ ___________________________________________________________________________}
+
+CONST
+    { The user's aircraft is always index 0.                                     }
+   XPLM_USER_AIRCRAFT   = 0;
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMPlaneDrawState_t
+    
+    This structure contains additional plane parameter info to be passed to
+    draw plane.  Make sure to fill in the size of the structure field with
+    sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you
+    knew about when compiling your plugin (since more fields may be added
+    later).
+    
+    Most of these fields are ratios from 0 to 1 for control input.  X-Plane
+    calculates what the actual controls look like based on the .acf file for
+    that airplane.  Note for the yoke inputs, this is what the pilot of the
+    plane has commanded (post artificial stability system if there were one)
+    and affects ailerons, rudder, etc.  It is not necessarily related to the
+    actual position of the plane's surfaces!
+   }
+TYPE
+   XPLMPlaneDrawState_t = RECORD
+     { The size of the draw state struct.                                         }
+     structSize               : Integer;
+     { A ratio from [0..1] describing how far the landing gear is extended.       }
+     gearPosition             : Single;
+     { Ratio of flap deployment, 0 = up, 1 = full deploy.                         }
+     flapRatio                : Single;
+     { Ratio of spoiler deployment, 0 = none, 1 = full deploy.                    }
+     spoilerRatio             : Single;
+     { Ratio of speed brake deployment, 0 = none, 1 = full deploy.                }
+     speedBrakeRatio          : Single;
+     { Ratio of slat deployment, 0 = none, 1 = full deploy.                       }
+     slatRatio                : Single;
+     { Wing sweep ratio, 0 = forward, 1 = swept.                                  }
+     wingSweep                : Single;
+     { Thrust power, 0 = none, 1 = full fwd, -1 = full reverse.                   }
+     thrust                   : Single;
+     { Total pitch input for this plane.                                          }
+     yokePitch                : Single;
+     { Total Heading input for this plane.                                        }
+     yokeHeading              : Single;
+     { Total Roll input for this plane.                                           }
+     yokeRoll                 : Single;
+   END;
+   PXPLMPlaneDrawState_t = ^XPLMPlaneDrawState_t;
+{$ENDIF XPLM_DEPRECATED}
+   {
+    XPLMCountAircraft
+    
+    This function returns the number of aircraft X-Plane is capable of having,
+    as well as the number of aircraft that are currently active.  These numbers
+    count the user's aircraft.  It can also return the plugin that is currently
+    controlling aircraft.  In X-Plane 7, this routine reflects the number of
+    aircraft the user has enabled in the rendering options window.
+   }
+   PROCEDURE XPLMCountAircraft(
+                                        outTotalAircraft    : PInteger;
+                                        outActiveAircraft   : PInteger;
+                                        outController       : PXPLMPluginID);
+    cdecl; external XPLM_DLL;
+   {
+    XPLMGetNthAircraftModel
+    
+    This function returns the aircraft model for the Nth aircraft.  Indices are
+    zero based, with zero being the user's aircraft.  The file name should be
+    at least 256 chars in length; the path should be at least 512 chars in
+    length.
+   }
+   PROCEDURE XPLMGetNthAircraftModel(
+                                        inIndex             : Integer;
+                                        outFileName         : XPLMString;
+                                        outPath             : XPLMString);
+    cdecl; external XPLM_DLL;
+{___________________________________________________________________________
+ * EXCLUSIVE AIRCRAFT ACCESS
+ ___________________________________________________________________________}
+{
+   The following routines require exclusive access to the airplane APIs. Only
+   one plugin may have this access at a time.
+}
+
+
+   {
+    XPLMPlanesAvailable_f
+    
+    Your airplanes available callback is called when another plugin gives up
+    access to the multiplayer planes.  Use this to wait for access to
+    multiplayer.
+   }
+TYPE
+     XPLMPlanesAvailable_f = PROCEDURE(
+                                    inRefcon            : pointer); cdecl;
+
+   {
+    XPLMAcquirePlanes
+    
+    XPLMAcquirePlanes grants your plugin exclusive access to the aircraft.  It
+    returns 1 if you gain access, 0 if you do not.
+    
+    inAircraft - pass in an array of pointers to strings specifying the planes
+    you want loaded.  For any plane index you do not want loaded, pass a
+    0-length string.  Other strings should be full paths with the .acf
+    extension.  NULL terminates this array, or pass NULL if there are no planes
+    you want loaded.
+    
+    If you pass in a callback and do not receive access to the planes your
+    callback will be called when the airplanes are available. If you do receive
+    airplane access, your callback will not be called.
+   }
+   FUNCTION XPLMAcquirePlanes(
+                                        inAircraft          : PXPLMString;    { Can be nil }
+                                        inCallback          : XPLMPlanesAvailable_f;
+                                        inRefcon            : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMReleasePlanes
+    
+    Call this function to release access to the planes.  Note that if you are
+    disabled, access to planes is released for you and you must reacquire it.
+   }
+   PROCEDURE XPLMReleasePlanes;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetActiveAircraftCount
+    
+    This routine sets the number of active planes.  If you pass in a number
+    higher than the total number of planes availables, only the total number of
+    planes available is actually used.
+   }
+   PROCEDURE XPLMSetActiveAircraftCount(
+                                        inCount             : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAircraftModel
+    
+    This routine loads an aircraft model.  It may only be called if you have
+    exclusive access to the airplane APIs.  Pass in the path of the model with
+    the .acf extension.  The index is zero based, but you may not pass in 0
+    (use XPLMSetUsersAircraft to load the user's aircracft).
+   }
+   PROCEDURE XPLMSetAircraftModel(
+                                        inIndex             : Integer;
+                                        inAircraftPath      : XPLMString);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDisableAIForPlane
+    
+    This routine turns off X-Plane's AI for a given plane.  The plane will
+    continue to draw and be a real plane in X-Plane, but will not move itself.
+   }
+   PROCEDURE XPLMDisableAIForPlane(
+                                        inPlaneIndex        : Integer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMDrawAircraft
+    
+    WARNING: Aircraft drawing via this API is deprecated and WILL NOT WORK in
+    future versions of X-Plane.  Use XPLMInstance for 3-d drawing of custom
+    aircraft models.
+    
+    This routine draws an aircraft.  It can only be called from a 3-d drawing
+    callback.  Pass in the position of the plane in OpenGL local coordinates
+    and the orientation of the plane.  A 1 for full drawing indicates that the
+    whole plane must be drawn; a 0 indicates you only need the nav lights
+    drawn. (This saves rendering time when planes are far away.)
+   }
+   PROCEDURE XPLMDrawAircraft(
+                                        inPlaneIndex        : Integer;
+                                        inX                 : Single;
+                                        inY                 : Single;
+                                        inZ                 : Single;
+                                        inPitch             : Single;
+                                        inRoll              : Single;
+                                        inYaw               : Single;
+                                        inFullDraw          : Integer;
+                                        inDrawStateInfo     : PXPLMPlaneDrawState_t);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM_DEPRECATED}
+
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMReinitUsersPlane
+    
+    WARNING: DO NOT USE.  Use XPLMPlaceUserAtAirport or
+    XPLMPlaceUserAtLocation.
+    
+    This function recomputes the derived flight model data from the aircraft
+    structure in memory.  If you have used the data access layer to modify the
+    aircraft structure, use this routine to resynchronize X-Plane; since
+    X-Plane works at least partly from derived values, the sim will not behave
+    properly until this is called.
+    
+    WARNING: this routine does not necessarily place the airplane at the
+    airport; use XPLMSetUsersAircraft to be compatible.  This routine is
+    provided to do special experimentation with flight models without resetting
+    flight.
+   }
+   PROCEDURE XPLMReinitUsersPlane;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM_DEPRECATED}
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMPlugin.pas b/SDK/Delphi/XPLM/XPLMPlugin.pas
new file mode 100644
index 0000000..6a5f268
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMPlugin.pas
@@ -0,0 +1,448 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMPlugin;
+INTERFACE
+{
+   These APIs provide facilities to find and work with other plugins and
+   manage other plugins.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * FINDING PLUGINS
+ ___________________________________________________________________________}
+{
+   These APIs allow you to find another plugin or yourself, or iterate across
+   all plugins.  For example, if you wrote an FMS plugin that needed to talk
+   to an autopilot plugin, you could use these APIs to locate the autopilot
+   plugin.
+}
+
+
+   {
+    XPLMGetMyID
+    
+    This routine returns the plugin ID of the calling plug-in.  Call this to
+    get your own ID.
+   }
+   FUNCTION XPLMGetMyID: XPLMPluginID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCountPlugins
+    
+    This routine returns the total number of plug-ins that are loaded, both
+    disabled and enabled.
+   }
+   FUNCTION XPLMCountPlugins: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetNthPlugin
+    
+    This routine returns the ID of a plug-in by index.  Index is 0 based from 0
+    to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary
+    order.
+   }
+   FUNCTION XPLMGetNthPlugin(
+                                        inIndex             : Integer) : XPLMPluginID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMFindPluginByPath
+    
+    This routine returns the plug-in ID of the plug-in whose file exists at the
+    passed in absolute file system path.  XPLM_NO_PLUGIN_ID is returned if the
+    path does not point to a currently loaded plug-in.
+   }
+   FUNCTION XPLMFindPluginByPath(
+                                        inPath              : XPLMString) : XPLMPluginID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMFindPluginBySignature
+    
+    This routine returns the plug-in ID of the plug-in whose signature matches
+    what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this
+    signature.  Signatures are the best way to identify another plug-in as they
+    are independent of the file system path of a plug-in or the human-readable
+    plug-in name, and should be unique for all plug-ins.  Use this routine to
+    locate another plugin that your plugin interoperates with
+   }
+   FUNCTION XPLMFindPluginBySignature(
+                                        inSignature         : XPLMString) : XPLMPluginID;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetPluginInfo
+    
+    This routine returns information about a plug-in.  Each parameter should be
+    a pointer to a buffer of at least
+    256 characters, or NULL to not receive the information.
+    
+    outName - the human-readable name of the plug-in. outFilePath - the
+    absolute file path to the file that contains this plug-in. outSignature - a
+    unique string that identifies this plug-in. outDescription - a
+    human-readable description of this plug-in.
+   }
+   PROCEDURE XPLMGetPluginInfo(
+                                        inPlugin            : XPLMPluginID;
+                                        outName             : XPLMString;    { Can be nil }
+                                        outFilePath         : XPLMString;    { Can be nil }
+                                        outSignature        : XPLMString;    { Can be nil }
+                                        outDescription      : XPLMString);    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * ENABLING/DISABLING PLUG-INS
+ ___________________________________________________________________________}
+{
+   These routines are used to work with plug-ins and manage them.  Most
+   plugins will not need to use these APIs.
+}
+
+
+   {
+    XPLMIsPluginEnabled
+    
+    Returns whether the specified plug-in is enabled for running.
+   }
+   FUNCTION XPLMIsPluginEnabled(
+                                        inPluginID          : XPLMPluginID) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMEnablePlugin
+    
+    This routine enables a plug-in if it is not already enabled. It returns 1
+    if the plugin was enabled or successfully enables itself, 0 if it does not.
+    Plugins may fail to enable (for example, if resources cannot be acquired)
+    by returning 0 from their XPluginEnable callback.
+   }
+   FUNCTION XPLMEnablePlugin(
+                                        inPluginID          : XPLMPluginID) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDisablePlugin
+    
+    This routine disableds an enabled plug-in.
+   }
+   PROCEDURE XPLMDisablePlugin(
+                                        inPluginID          : XPLMPluginID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMReloadPlugins
+    
+    This routine reloads all plug-ins.  Once this routine is called and you
+    return from the callback you were within (e.g. a menu select callback) you
+    will receive your XPluginDisable and XPluginStop callbacks and your DLL
+    will be unloaded, then the start process happens as if the sim was starting
+    up.
+   }
+   PROCEDURE XPLMReloadPlugins;
+    cdecl; external XPLM_DLL;
+
+{___________________________________________________________________________
+ * INTERPLUGIN MESSAGING
+ ___________________________________________________________________________}
+{
+   Plugin messages are defined as 32-bit integers.  Messages below 0x00FFFFFF
+   are reserved for X-Plane and the plugin SDK.
+   
+   Messages come with a pointer parameter; the meaning of this pointer depends
+   on the message itself. In some messages, the pointer parameter  contains an
+   actual typed pointer to data that can be inspected in the plugin; in these
+   cases the documentation will state that the parameter "points to"
+   information.
+   
+   in other cases, the value of the pointer is actually an integral number
+   stuffed into the pointer's storage. In these second cases, the pointer
+   parameter needs to be cast, not dereferenced. In these caess, the
+   documentation will state that the parameter "contains" a value, which will
+   always be an integral type.
+   
+   Some messages don't use the pointer parameter - in this case your plugin
+   should ignore it.
+   
+   Messages have two conceptual uses: notifications and commands.  Commands
+   are sent from one plugin to another to induce behavior; notifications are
+   sent from one plugin to all others for informational purposes.  It is
+   important that commands and notifications not have the same values because
+   this could cause a notification sent by one plugin to accidentally induce a
+   command in another.
+   
+   By convention, plugin-defined notifications should have the high bit set
+   (e.g. be greater or equal to unsigned 0x8000000) while commands should have
+   this bit be cleared.
+   
+   The following messages are sent to your plugin by X-Plane.
+}
+
+
+CONST
+    { This message is sent to your plugin whenever the user's plane crashes. The }
+    { parameter is ignored.                                                      }
+   XPLM_MSG_PLANE_CRASHED = 101;
+
+    { This message is sent to your plugin whenever a new plane is loaded.  The   }
+    { parameter contains the index number of the plane being loaded; 0 indicates }
+    { the user's plane.                                                          }
+   XPLM_MSG_PLANE_LOADED = 102;
+
+    { This messages is sent whenever the user's plane is positioned at a new     }
+    { airport. The parameter is ignored.                                         }
+   XPLM_MSG_AIRPORT_LOADED = 103;
+
+    { This message is sent whenever new scenery is loaded.  Use datarefs to      }
+    { determine the new scenery files that were loaded. The parameter is ignored.}
+   XPLM_MSG_SCENERY_LOADED = 104;
+
+    { This message is sent whenever the user adjusts the number of X-Plane       }
+    { aircraft models.  You must use XPLMCountPlanes to find out how many planes }
+    { are now available.  This message will only be sent in XP7 and higher       }
+    { because in XP6 the number of aircraft is not user-adjustable. The parameter}
+    { is ignored.                                                                }
+   XPLM_MSG_AIRPLANE_COUNT_CHANGED = 105;
+
+{$IFDEF XPLM200}
+CONST
+    { This message is sent to your plugin whenever a plane is unloaded.  The     }
+    { parameter contains the index number of the plane being unloaded; 0         }
+    { indicates the user's plane.  The parameter is of type int, passed as the   }
+    { value of the pointer.  (That is: the parameter is an int, not a pointer to }
+    { an int.)                                                                   }
+   XPLM_MSG_PLANE_UNLOADED = 106;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM210}
+CONST
+    { This message is sent to your plugin right before X-Plane writes its        }
+    { preferences file.  You can use this for two purposes: to write your own    }
+    { preferences, and to modify any datarefs to influence preferences output.   }
+    { For example, if your plugin temporarily modifies saved preferences, you can}
+    { put them back to their default values here to avoid having the tweaks be   }
+    { persisted if your plugin is not loaded on the next invocation of X-Plane.  }
+    { The parameter is ignored.                                                  }
+   XPLM_MSG_WILL_WRITE_PREFS = 107;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM210}
+    { This message is sent to your plugin right after a livery is loaded for an  }
+    { airplane.  You can use this to check the new livery (via datarefs) and     }
+    { react accordingly.  The parameter contains the index number of the aircraft}
+    { whose livery is changing.                                                  }
+   XPLM_MSG_LIVERY_LOADED = 108;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM301}
+CONST
+    { Sent to your plugin right before X-Plane enters virtual reality mode (at   }
+    { which time any windows that are not positioned in VR mode will no longer be}
+    { visible to the user). The parameter is unused and should be ignored.       }
+   XPLM_MSG_ENTERED_VR  = 109;
+{$ENDIF XPLM301}
+
+{$IFDEF XPLM301}
+    { Sent to your plugin right before X-Plane leaves virtual reality mode (at   }
+    { which time you may want to clean up windows that are positioned in VR      }
+    { mode). The parameter is unused and should be ignored.                      }
+   XPLM_MSG_EXITING_VR  = 110;
+{$ENDIF XPLM301}
+
+{$IFDEF XPLM303}
+CONST
+    { Sent to your plugin if another plugin wants to take over AI planes. If you }
+    { are a synthetic traffic provider,  that probably means a plugin for an     }
+    { online network has connected and wants to supply aircraft flown by real    }
+    { humans and you should cease to provide synthetic traffic. If however you   }
+    { are providing online traffic from real humans,  you probably don't want to }
+    { disconnect, in which case you just ignore this message. The sender is the  }
+    { plugin ID of the plugin asking for control of the planes now. You can use  }
+    { it to find out who is requesting and whether you should yield to them.     }
+    { Synthetic traffic providers should always yield to online networks. The    }
+    { parameter is unused and should be ignored.                                 }
+   XPLM_MSG_RELEASE_PLANES = 111;
+{$ENDIF XPLM303}
+
+{$IFDEF XPLM400}
+CONST
+    { Sent to your plugin after FMOD sound banks are loaded. The parameter is the}
+    { XPLMBankID enum in XPLMSound.h, 0 for the master bank and 1 for the radio  }
+    { bank.                                                                      }
+   XPLM_MSG_FMOD_BANK_LOADED = 112;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+    { Sent to your plugin before FMOD sound banks are unloaded. Any associated   }
+    { resources should be cleaned up at this point. The parameter is the         }
+    { XPLMBankID enum in XPLMSound.h, 0 for the master bank and 1 for the radio  }
+    { bank.                                                                      }
+   XPLM_MSG_FMOD_BANK_UNLOADING = 113;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+    { Sent to your plugin per-frame (at-most) when/if datarefs are added. It will}
+    { include the new data ref total count so that your plugin can keep a local  }
+    { cache of the total, see what's changed and know which ones to inquire about}
+    { if it cares.                                                               }
+    {                                                                            }
+    { This message is only sent to plugins that enable the                       }
+    { XPLM_WANTS_DATAREF_NOTIFICATIONS feature.                                  }
+   XPLM_MSG_DATAREFS_ADDED = 114;
+{$ENDIF XPLM400}
+
+   {
+    XPLMSendMessageToPlugin
+    
+    This function sends a message to another plug-in or X-Plane.  Pass
+    XPLM_NO_PLUGIN_ID to broadcast to all plug-ins.  Only enabled plug-ins with
+    a message receive function receive the message.
+   }
+   PROCEDURE XPLMSendMessageToPlugin(
+                                        inPlugin            : XPLMPluginID;
+                                        inMessage           : Integer;
+                                        inParam             : pointer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM200}
+{___________________________________________________________________________
+ * Plugin Features API
+ ___________________________________________________________________________}
+{
+   The plugin features API allows your plugin to "sign up" for additional
+   capabilities and plugin system features that are normally disabled for
+   backward compatibility or performance.  This allows advanced plugins to
+   "opt-in"  to new behavior.
+   
+   Each feature is defined by a permanent string name.  The feature string
+   names will vary with the particular installation of X-Plane, so plugins
+   should not expect a feature to be guaranteed present.
+   
+   XPLM_WANTS_REFLECTIONS
+   ----------------------
+   
+   Available in the SDK 2.0 and later for X-Plane 9, enabling this capability
+   causes your plugin to receive drawing hook callbacks when X-Plane builds
+   its off-screen reflection and shadow rendering passes. Plugins should
+   enable this and examine the dataref sim/graphics/view/plane_render_type to
+   determine whether the drawing callback is for a reflection, shadow
+   calculation, or the main screen. Rendering can be simlified or omitted for
+   reflections, and non-solid drawing should be skipped for shadow
+   calculations.
+   
+   **Note**: direct drawing via draw callbacks is not recommended; use the
+     XPLMInstance API to create object models instead.
+   
+   XPLM_USE_NATIVE_PATHS
+   ---------------------
+   
+   available in the SDK 2.1 and later for X-Plane 10, this modifies the plugin
+   system to use Unix-style paths on all operating systems. With this enabled:
+   
+   * OS X paths will match the native OS X Unix.
+   * Windows will use forward slashes but preserve C:\ or another drive letter
+     when using complete file paths.
+   * Linux uses its native file system path scheme.
+   
+   Without this enabled:
+   
+   * OS X will use CFM file paths separated by a colon.
+   * Windows will use back-slashes and conventional DOS paths.
+   * Linux uses its native file system path scheme.
+   
+   All plugins should enable this feature on OS X to access the native file
+   system.
+   
+   XPLM_USE_NATIVE_WIDGET_WINDOWS
+   ------------------------------
+   
+   Available in the SDK 3.0.2 SDK, this capability tells the widgets library
+   to use new, modern X-Plane backed XPLMDisplay windows to anchor all widget
+   trees.  Without it, widgets will always use legacy windows.
+   
+   Plugins should enable this to allow their widget hierarchies to respond to
+   the user's UI size settings and to map widget-based windwos to a VR HMD.
+   
+   Before enabling this, make sure any custom widget code in your plugin is
+   prepared to cope with the UI coordinate system not being th same as the
+   OpenGL window coordinate system.
+   
+   XPLM_WANTS_DATAREF_NOTIFICATIONS
+   --------------------------------
+   
+   Available in the SDK 4.0.0, this capability tells X-Plane to to send the
+   enabling plugin the new XPLM_MSG_DATAREFS_ADDED message any time new
+   datarefs are added. The SDK will coalesce consecutive dataref registrations
+   to minimize the number of messages sent.
+}
+
+
+   {
+    XPLMFeatureEnumerator_f
+    
+    You pass an XPLMFeatureEnumerator_f to get a list of all features supported
+    by a given version running version of X-Plane.  This routine is called once
+    for each feature.
+   }
+TYPE
+     XPLMFeatureEnumerator_f = PROCEDURE(
+                                    inFeature           : XPLMString;
+                                    inRef               : pointer); cdecl;
+
+   {
+    XPLMHasFeature
+    
+    This returns 1 if the given installation of X-Plane supports a feature, or
+    0 if it does not.
+   }
+   FUNCTION XPLMHasFeature(
+                                        inFeature           : XPLMString) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMIsFeatureEnabled
+    
+    This returns 1 if a feature is currently enabled for your plugin, or 0 if
+    it is not enabled.  It is an error to call this routine with an unsupported
+    feature.
+   }
+   FUNCTION XPLMIsFeatureEnabled(
+                                        inFeature           : XPLMString) : Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMEnableFeature
+    
+    This routine enables or disables a feature for your plugin.  This will
+    change the running behavior of X-Plane and your plugin in some way,
+    depending on the feature.
+   }
+   PROCEDURE XPLMEnableFeature(
+                                        inFeature           : XPLMString;
+                                        inEnable            : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMEnumerateFeatures
+    
+    This routine calls your enumerator callback once for each feature that this
+    running version of X-Plane supports. Use this routine to determine all of
+    the features that X-Plane can support.
+   }
+   PROCEDURE XPLMEnumerateFeatures(
+                                        inEnumerator        : XPLMFeatureEnumerator_f;
+                                        inRef               : pointer);
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM200}
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMProcessing.pas b/SDK/Delphi/XPLM/XPLMProcessing.pas
new file mode 100644
index 0000000..266fc9b
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMProcessing.pas
@@ -0,0 +1,257 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMProcessing;
+INTERFACE
+{
+   This API allows you to get regular callbacks during the flight loop, the
+   part of X-Plane where the plane's position calculates the physics of
+   flight, etc. Use these APIs to accomplish periodic tasks like logging data
+   and performing I/O.
+   
+   You can receive a callback either just before or just after the per-frame
+   physics calculations happen - you can use post-flightmodel callbacks to
+   "patch" the flight model after it has run.
+   
+   If the user has set the number of flight model iterations per frame greater
+   than one your plugin will _not_ see this; these integrations run on the
+   sub-section of the flight model where iterations improve responsiveness
+   (e.g. physical integration, not simple systems tracking) and are thus
+   opaque to plugins.
+   
+   Flight loop scheduling, when scheduled by time, is scheduled by a "first
+   callback after the deadline" schedule, e.g. your callbacks will always be
+   slightly late to ensure that we don't run faster than your deadline.
+   
+   WARNING: Do NOT use these callbacks to draw! You cannot draw during flight
+   loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info)
+   for graphics or the XPLMInstance functions for aircraft or models. (One
+   exception: you can use a post-flight loop callback to update your own
+   off-screen FBOs.)
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * FLIGHT LOOP CALLBACKS
+ ___________________________________________________________________________}
+
+{$IFDEF XPLM210}
+   {
+    XPLMFlightLoopPhaseType
+    
+    You can register a flight loop callback to run either before or after the
+    flight model is integrated by X-Plane.
+   }
+TYPE
+   XPLMFlightLoopPhaseType = (
+     { Your callback runs before X-Plane integrates the flight model.             }
+      xplm_FlightLoop_Phase_BeforeFlightModel  = 0
+ 
+     { Your callback runs after X-Plane integrates the flight model.              }
+     ,xplm_FlightLoop_Phase_AfterFlightModel   = 1
+ 
+   );
+   PXPLMFlightLoopPhaseType = ^XPLMFlightLoopPhaseType;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM210}
+   {
+    XPLMFlightLoopID
+    
+    This is an opaque identifier for a flight loop callback. You can use this
+    identifier to easily track and remove your callbacks, or to use the new
+    flight loop APIs.
+   }
+   XPLMFlightLoopID = pointer;
+   PXPLMFlightLoopID = ^XPLMFlightLoopID;
+{$ENDIF XPLM210}
+
+   {
+    XPLMFlightLoop_f
+    
+    This is your flight loop callback. Each time the flight loop is iterated
+    through, you receive this call at the end.
+    
+    Flight loop callbacks receive a number of input timing parameters. These
+    input timing parameters are not particularly useful; you may need to track
+    your own timing data (e.g. by reading datarefs). The input parameters are:
+    
+    - inElapsedSinceLastCall: the wall time since your last callback.
+    - inElapsedTimeSinceLastFlightLoop: the wall time since any flight loop was
+      dispatched.
+    - inCounter: a monotonically increasing counter, bumped once per flight
+      loop dispatch from the sim.
+    - inRefcon: your own pointer constant provided when you registered yor
+      callback.
+    
+    Your return value controls when you will next be called.
+    
+     - Return 0 to stop receiving callbacks.
+     - Return a positive number to specify how many seconds until the next
+       callback. (You will be called at or after this time, not before.)
+     - Return a negative number to specify how many loops must go by until you
+       are called. For example, -1.0 means call me the very next loop.
+    
+    Try to run your flight loop as infrequently as is practical, and suspend it
+    (using return value 0) when you do not need it; lots of flight loop
+    callbacks that do nothing lowers X-Plane's frame rate.
+    
+    Your callback will NOT be unregistered if you return 0; it will merely be
+    inactive.
+   }
+TYPE
+     XPLMFlightLoop_f = FUNCTION(
+                                    inElapsedSinceLastCall: Single;
+                                    inElapsedTimeSinceLastFlightLoop: Single;
+                                    inCounter           : Integer;
+                                    inRefcon            : pointer) : Single; cdecl;
+
+{$IFDEF XPLM210}
+   {
+    XPLMCreateFlightLoop_t
+    
+    XPLMCreateFlightLoop_t contains the parameters to create a new flight loop
+    callback. The structure may be expanded in future SDKs - always set
+    structSize to the size of your structure in bytes.
+   }
+TYPE
+   XPLMCreateFlightLoop_t = RECORD
+     structSize               : Integer;
+     phase                    : XPLMFlightLoopPhaseType;
+     callbackFunc             : XPLMFlightLoop_f;
+     refcon                   : pointer;
+   END;
+   PXPLMCreateFlightLoop_t = ^XPLMCreateFlightLoop_t;
+{$ENDIF XPLM210}
+
+   {
+    XPLMGetElapsedTime
+    
+    This routine returns the elapsed time since the sim started up in decimal
+    seconds. This is a wall timer; it keeps counting upward even if the sim is
+    pasued.
+    
+    __WARNING__: XPLMGetElapsedTime is not a very good timer!  It lacks
+    precision in both its data type and its source.  Do not attempt to use it
+    for timing critical applications like network multiplayer.
+   }
+   FUNCTION XPLMGetElapsedTime: Single;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetCycleNumber
+    
+    This routine returns a counter starting at zero for each sim cycle
+    computed/video frame rendered.
+   }
+   FUNCTION XPLMGetCycleNumber: Integer;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMRegisterFlightLoopCallback
+    
+    This routine registers your flight loop callback. Pass in a pointer to a
+    flight loop function and a refcon (an optional reference value determined
+    by you). inInterval defines when you will be called. Pass in a positive
+    number to specify seconds from registration time to the next callback. Pass
+    in a negative number to indicate when you will be called (e.g. pass -1 to
+    be called at the next cylcle). Pass 0 to not be called; your callback will
+    be inactive.
+    
+    (This legacy function only installs pre-flight-loop callbacks; use
+    XPLMCreateFlightLoop for more control.)
+   }
+   PROCEDURE XPLMRegisterFlightLoopCallback(
+                                        inFlightLoop        : XPLMFlightLoop_f;
+                                        inInterval          : Single;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterFlightLoopCallback
+    
+    This routine unregisters your flight loop callback. Do NOT call it from
+    your flight loop callback. Once your flight loop callback is unregistered,
+    it will not be called again.
+    
+    Only use this on flight loops registered via
+    XPLMRegisterFlightLoopCallback.
+   }
+   PROCEDURE XPLMUnregisterFlightLoopCallback(
+                                        inFlightLoop        : XPLMFlightLoop_f;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetFlightLoopCallbackInterval
+    
+    This routine sets when a callback will be called. Do NOT call it from your
+    callback; use the return value of the callback to change your callback
+    interval from inside your callback.
+    
+    inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback;
+    positive for seconds, negative for cycles, and 0 for deactivating the
+    callback. If inRelativeToNow is 1, times are from the time of this call;
+    otherwise they are from the time the callback was last called (or the time
+    it was registered if it has never been called.
+   }
+   PROCEDURE XPLMSetFlightLoopCallbackInterval(
+                                        inFlightLoop        : XPLMFlightLoop_f;
+                                        inInterval          : Single;
+                                        inRelativeToNow     : Integer;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM210}
+   {
+    XPLMCreateFlightLoop
+    
+    This routine creates a flight loop callback and returns its ID. The flight
+    loop callback is created using the input param struct, and is inited to be
+    unscheduled.
+   }
+   FUNCTION XPLMCreateFlightLoop(
+                                        inParams            : PXPLMCreateFlightLoop_t) : XPLMFlightLoopID;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM210}
+   {
+    XPLMDestroyFlightLoop
+    
+    This routine destroys a flight loop callback by ID. Only call it on flight
+    loops created with the newer XPLMCreateFlightLoop API.
+   }
+   PROCEDURE XPLMDestroyFlightLoop(
+                                        inFlightLoopID      : XPLMFlightLoopID);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM210}
+   {
+    XPLMScheduleFlightLoop
+    
+    This routine schedules a flight loop callback for future execution. If
+    inInterval is negative, it is run in a certain number of frames based on
+    the absolute value of the input. If the interval is positive, it is a
+    duration in seconds.
+    
+    If inRelativeToNow is true, times are interpreted relative to the time this
+    routine is called; otherwise they are relative to the last call time or the
+    time the flight loop was registered (if never called).
+   }
+   PROCEDURE XPLMScheduleFlightLoop(
+                                        inFlightLoopID      : XPLMFlightLoopID;
+                                        inInterval          : Single;
+                                        inRelativeToNow     : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM210}
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMScenery.pas b/SDK/Delphi/XPLM/XPLMScenery.pas
new file mode 100644
index 0000000..f0b58f0
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMScenery.pas
@@ -0,0 +1,434 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMScenery;
+INTERFACE
+{
+   This package contains APIs to interact with X-Plane's scenery system.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{$IFDEF XPLM200}
+{___________________________________________________________________________
+ * Terrain Y-Testing
+ ___________________________________________________________________________}
+{
+   The Y-testing API allows you to locate the physical scenery mesh. This
+   would be used to place dynamic graphics on top of the ground in a plausible
+   way or do physics interactions.
+   
+   The Y-test API works via probe objects, which are allocated by your plugin
+   and used to query terrain. Probe objects exist both to capture which
+   algorithm you have requested (see probe types) and also to cache query
+   information.
+   
+   Performance Guidelines
+   ----------------------
+   
+   It is generally faster to use the same probe for nearby points and
+   different probes for different points. Try not to allocate more than
+   "hundreds" of probes at most. Share probes if you need more. Generally,
+   probing operations are expensive, and should be avoided via caching when
+   possible.
+   
+   Y testing returns a location on the terrain, a normal vector, and a
+   velocity vector. The normal vector tells you the slope of the terrain at
+   that point. The velocity vector tells you if that terrain is moving (and is
+   in meters/second). For example, if your Y test hits the aircraft carrier
+   deck, this tells you the velocity of that point on the deck.
+   
+   Note: the Y-testing API is limited to probing the loaded scenery area,
+   which is approximately 300x300 km in X-Plane 9. Probes outside this area
+   will return the height of a 0 MSL sphere.
+}
+
+
+   {
+    XPLMProbeType
+    
+    XPLMProbeType defines the type of terrain probe - each probe has a
+    different algorithm. (Only one type of probe is provided right now, but
+    future APIs will expose more flexible or powerful or useful probes.
+   }
+TYPE
+   XPLMProbeType = (
+     { The Y probe gives you the location of the tallest physical scenery along   }
+     { the Y axis going through the queried point.                                }
+      xplm_ProbeY                              = 0
+ 
+   );
+   PXPLMProbeType = ^XPLMProbeType;
+
+   {
+    XPLMProbeResult
+    
+    Probe results - possible results from a probe query.
+   }
+   XPLMProbeResult = (
+     { The probe hit terrain and returned valid values.                           }
+      xplm_ProbeHitTerrain                     = 0
+ 
+     { An error in the API call.  Either the probe struct size is bad, the probe  }
+     { is invalid, or the type is mismatched for the specific query call.         }
+     ,xplm_ProbeError                          = 1
+ 
+     { The probe call succeeded but there is no terrain under this point (perhaps }
+     { it is off the side of the planet?)                                         }
+     ,xplm_ProbeMissed                         = 2
+ 
+   );
+   PXPLMProbeResult = ^XPLMProbeResult;
+
+   {
+    XPLMProbeRef
+    
+    An XPLMProbeRef is an opaque handle to a probe, used for querying the
+    terrain.
+   }
+   XPLMProbeRef = pointer;
+   PXPLMProbeRef = ^XPLMProbeRef;
+
+   {
+    XPLMProbeInfo_t
+    
+    XPLMProbeInfo_t contains the results of a probe call. Make sure to set
+    structSize to the size of the struct before using it.
+   }
+   XPLMProbeInfo_t = RECORD
+     { Size of structure in bytes - always set this before calling the XPLM.      }
+     structSize               : Integer;
+     { Resulting X location of the terrain point we hit, in local OpenGL          }
+     { coordinates.                                                               }
+     locationX                : Single;
+     { Resulting Y location of the terrain point we hit, in local OpenGL          }
+     { coordinates.                                                               }
+     locationY                : Single;
+     { Resulting Z location of the terrain point we hit, in local OpenGL          }
+     { coordinates.                                                               }
+     locationZ                : Single;
+     { X component of the normal vector to the terrain we found.                  }
+     normalX                  : Single;
+     { Y component of the normal vector to the terrain we found.                  }
+     normalY                  : Single;
+     { Z component of the normal vector to the terrain we found.                  }
+     normalZ                  : Single;
+     { X component of the velocity vector of the terrain we found.                }
+     velocityX                : Single;
+     { Y component of the velocity vector of the terrain we found.                }
+     velocityY                : Single;
+     { Z component of the velocity vector of the terrain we found.                }
+     velocityZ                : Single;
+     { Tells if the surface we hit is water (otherwise it is land).               }
+     is_wet                   : Integer;
+   END;
+   PXPLMProbeInfo_t = ^XPLMProbeInfo_t;
+
+   {
+    XPLMCreateProbe
+    
+    Creates a new probe object of a given type and returns.
+   }
+   FUNCTION XPLMCreateProbe(
+                                        inProbeType         : XPLMProbeType) : XPLMProbeRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDestroyProbe
+    
+    Deallocates an existing probe object.
+   }
+   PROCEDURE XPLMDestroyProbe(
+                                        inProbe             : XPLMProbeRef);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMProbeTerrainXYZ
+    
+    Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe
+    object, and an XPLMProbeInfo_t struct that has its structSize member set
+    properly. Other fields are filled in if we hit terrain, and a probe result
+    is returned.
+   }
+   FUNCTION XPLMProbeTerrainXYZ(
+                                        inProbe             : XPLMProbeRef;
+                                        inX                 : Single;
+                                        inY                 : Single;
+                                        inZ                 : Single;
+                                        outInfo             : PXPLMProbeInfo_t) : XPLMProbeResult;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM200}
+{$IFDEF XPLM300}
+{___________________________________________________________________________
+ * Magnetic Variation
+ ___________________________________________________________________________}
+{
+   Use the magnetic variation (more properly, the "magnetic declination") API
+   to find the offset of magnetic north from true north at a given latitude
+   and longitude within the simulator.
+   
+   In the real world, the Earth's magnetic field is irregular, such that true
+   north (the direction along a meridian toward the north pole) does not
+   necessarily match what a magnetic compass shows as north.
+   
+   Using this API ensures that you present the same offsets to users as
+   X-Plane's built-in instruments.
+}
+
+
+   {
+    XPLMGetMagneticVariation
+    
+    Returns X-Plane's simulated magnetic variation (declination) at the
+    indication latitude and longitude.
+   }
+   FUNCTION XPLMGetMagneticVariation(
+                                        latitude            : Real;
+                                        longitude           : Real) : Single;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDegTrueToDegMagnetic
+    
+    Converts a heading in degrees relative to true north into a value relative
+    to magnetic north at the user's current location.
+   }
+   FUNCTION XPLMDegTrueToDegMagnetic(
+                                        headingDegreesTrue  : Single) : Single;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMDegMagneticToDegTrue
+    
+    Converts a heading in degrees relative to magnetic north at the user's
+    current location into a value relative to true north.
+   }
+   FUNCTION XPLMDegMagneticToDegTrue(
+                                        headingDegreesMagnetic: Single) : Single;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM300}
+{___________________________________________________________________________
+ * Object Drawing
+ ___________________________________________________________________________}
+{
+   The object drawing routines let you load and draw X-Plane OBJ files.
+   Objects are loaded by file path and managed via an opaque handle. X-Plane
+   naturally reference counts objects, so it is important that you balance
+   every successful call to XPLMLoadObject with a call to XPLMUnloadObject!
+}
+
+
+{$IFDEF XPLM200}
+TYPE
+   {
+    XPLMObjectRef
+    
+    An XPLMObjectRef is a opaque handle to an .obj file that has been loaded
+    into memory.
+   }
+   XPLMObjectRef = pointer;
+   PXPLMObjectRef = ^XPLMObjectRef;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+   {
+    XPLMDrawInfo_t
+    
+    The XPLMDrawInfo_t structure contains positioning info for one object that
+    is to be drawn. Be sure to set structSize to the size of the structure for
+    future expansion.
+   }
+   XPLMDrawInfo_t = RECORD
+     { Set this to the size of this structure!                                    }
+     structSize               : Integer;
+     { X location of the object in local coordinates.                             }
+     x                        : Single;
+     { Y location of the object in local coordinates.                             }
+     y                        : Single;
+     { Z location of the object in local coordinates.                             }
+     z                        : Single;
+     { Pitch in degres to rotate the object, positive is up.                      }
+     pitch                    : Single;
+     { Heading in local coordinates to rotate the object, clockwise.              }
+     heading                  : Single;
+     { Roll to rotate the object.                                                 }
+     roll                     : Single;
+   END;
+   PXPLMDrawInfo_t = ^XPLMDrawInfo_t;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM210}
+   {
+    XPLMObjectLoaded_f
+    
+    You provide this callback when loading an object asynchronously; it will be
+    called once the object is loaded. Your refcon is passed back. The object
+    ref passed in is the newly loaded object (ready for use) or NULL if an
+    error occured.
+    
+    If your plugin is disabled, this callback will be delivered as soon as the
+    plugin is re-enabled. If your plugin is unloaded before this callback is
+    ever called, the SDK will release the object handle for you.
+   }
+TYPE
+     XPLMObjectLoaded_f = PROCEDURE(
+                                    inObject            : XPLMObjectRef;
+                                    inRefcon            : pointer); cdecl;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM200}
+   {
+    XPLMLoadObject
+    
+    This routine loads an OBJ file and returns a handle to it. If X-Plane has
+    already loaded the object, the handle to the existing object is returned.
+    Do not assume you will get the same handle back twice, but do make sure to
+    call unload once for every load to avoid "leaking" objects. The object will
+    be purged from memory when no plugins and no scenery are using it.
+    
+    The path for the object must be relative to the X-System base folder. If
+    the path is in the root of the X-System folder you may need to prepend ./
+    to it; loading objects in the root of the X-System folder is STRONGLY
+    discouraged - your plugin should not dump art resources in the root folder!
+    
+    XPLMLoadObject will return NULL if the object cannot be loaded (either
+    because it is not found or the file is misformatted). This routine will
+    load any object that can be used in the X-Plane scenery system.
+    
+    It is important that the datarefs an object uses for animation already be
+    registered before you load the object. For this reason it may be necessary
+    to defer object loading until the sim has fully started.
+   }
+   FUNCTION XPLMLoadObject(
+                                        inPath              : XPLMString) : XPLMObjectRef;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM210}
+   {
+    XPLMLoadObjectAsync
+    
+    This routine loads an object asynchronously; control is returned to you
+    immediately while X-Plane loads the object. The sim will not stop flying
+    while the object loads. For large objects, it may be several seconds before
+    the load finishes.
+    
+    You provide a callback function that is called once the load has completed.
+    Note that if the object cannot be loaded, you will not find out until the
+    callback function is called with a NULL object handle.
+    
+    There is no way to cancel an asynchronous object load; you must wait for
+    the load to complete and then release the object if it is no longer
+    desired.
+   }
+   PROCEDURE XPLMLoadObjectAsync(
+                                        inPath              : XPLMString;
+                                        inCallback          : XPLMObjectLoaded_f;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM210}
+
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMDrawObjects
+    
+    __Deprecation Warning__: use XPLMInstancing to draw 3-d objects by creating
+    instances, rather than these APIs from draw callbacks.
+    
+    XPLMDrawObjects draws an object from an OBJ file one or more times. You
+    pass in the object and an array of XPLMDrawInfo_t structs, one for each
+    place you would like the object to be drawn.
+    
+    X-Plane will attempt to cull the objects based on LOD and visibility, and
+    will pick the appropriate LOD.
+    
+    Lighting is a boolean; pass 1 to show the night version of object with
+    night-only lights lit up. Pass 0 to show the daytime version of the object.
+    
+    earth_relative controls the coordinate system. If this is 1, the rotations
+    you specify are applied to the object after its coordinate system is
+    transformed from local to earth-relative coordinates -- that is, an object
+    with no rotations will point toward true north and the Y axis will be up
+    against gravity. If this is 0, the object is drawn with your rotations from
+    local coordanates -- that is, an object with no rotations is drawn pointing
+    down the -Z axis and the Y axis of the object matches the local coordinate
+    Y axis.
+   }
+   PROCEDURE XPLMDrawObjects(
+                                        inObject            : XPLMObjectRef;
+                                        inCount             : Integer;
+                                        inLocations         : PXPLMDrawInfo_t;
+                                        lighting            : Integer;
+                                        earth_relative      : Integer);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM_DEPRECATED}
+
+{$IFDEF XPLM200}
+   {
+    XPLMUnloadObject
+    
+    This routine marks an object as no longer being used by your plugin.
+    Objects are reference counted: once no plugins are using an object, it is
+    purged from memory. Make sure to call XPLMUnloadObject once for each
+    successful call to XPLMLoadObject.
+   }
+   PROCEDURE XPLMUnloadObject(
+                                        inObject            : XPLMObjectRef);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+{___________________________________________________________________________
+ * Library Access
+ ___________________________________________________________________________}
+{
+   The library access routines allow you to locate scenery objects via the
+   X-Plane library system. Right now library access is only provided for
+   objects, allowing plugin-drawn objects to be extended using the library
+   system.
+}
+
+
+   {
+    XPLMLibraryEnumerator_f
+    
+    An XPLMLibraryEnumerator_f is a callback you provide that is called once
+    for each library element that is located. The returned paths will be
+    relative to the X-System folder.
+   }
+TYPE
+     XPLMLibraryEnumerator_f = PROCEDURE(
+                                    inFilePath          : XPLMString;
+                                    inRef               : pointer); cdecl;
+
+   {
+    XPLMLookupObjects
+    
+    This routine looks up a virtual path in the library system and returns all
+    matching elements. You provide a callback - one virtual path may match many
+    objects in the library. XPLMLookupObjects returns the number of objects
+    found.
+    
+    The latitude and longitude parameters specify the location the object will
+    be used. The library system allows for scenery packages to only provide
+    objects to certain local locations. Only objects that are allowed at the
+    latitude/longitude you provide will be returned.
+   }
+   FUNCTION XPLMLookupObjects(
+                                        inPath              : XPLMString;
+                                        inLatitude          : Single;
+                                        inLongitude         : Single;
+                                        enumerator          : XPLMLibraryEnumerator_f;
+                                        ref                 : pointer) : Integer;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM200}
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMSound.pas b/SDK/Delphi/XPLM/XPLMSound.pas
new file mode 100644
index 0000000..64242c3
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMSound.pas
@@ -0,0 +1,232 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMSound;
+INTERFACE
+{
+   This provides a minimal interface into the FMOD audio system. On the
+   simplest level, you can request that X-Plane plays an in-memory audio
+   buffer. This will work without linking to FMOD yourself. If you want to do
+   anything more, such as modifying the sound, or loading banks and triggering
+   your own events, you can get a pointer to the FMOD Studio instance.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{$IFDEF XPLM400}
+{___________________________________________________________________________
+ * FMOD ACCESS
+ ___________________________________________________________________________}
+
+   {
+    XPLMAudioBus
+    
+    This enumeration states the type of audio you wish to play - that is, the
+    part of the simulated environment that the audio belongs in. If you use
+    FMOD directly, note that COM1, COM2, Pilot and GND exist in a different
+    FMOD bank so you may see these channels being unloaded/reloaded
+    independently of the others. They may also be using a different
+    FMOD::System if the user has selected a dedicated headset output device.
+   }
+TYPE
+   XPLMAudioBus = (
+     { Incoming speech on COM1                                                    }
+      xplm_AudioRadioCom1                      = 0
+ 
+     { Incoming speech on COM2                                                    }
+     ,xplm_AudioRadioCom2                      = 1
+ 
+     { Pilot's own speech                                                         }
+     ,xplm_AudioRadioPilot                     = 2
+ 
+     { Copilot's own speech                                                       }
+     ,xplm_AudioRadioCopilot                   = 3
+ 
+     ,xplm_AudioExteriorAircraft               = 4
+ 
+     ,xplm_AudioExteriorEnvironment            = 5
+ 
+     ,xplm_AudioExteriorUnprocessed            = 6
+ 
+     ,xplm_AudioInterior                       = 7
+ 
+     ,xplm_AudioUI                             = 8
+ 
+     { Dedicated ground vehicle cable                                             }
+     ,xplm_AudioGround                         = 9
+ 
+     { Master bus. Not normally to be used directly.                              }
+     ,xplm_Master                              = 10
+ 
+   );
+   PXPLMAudioBus = ^XPLMAudioBus;
+
+   {
+    XPLMBankID
+    
+    These values are returned as the parameter of the
+    "XPLM_MSG_FMOD_BANK_LOADED" and "XPLM_MSG_FMOD_BANK_UNLOADING" messages.
+   }
+   XPLMBankID = (
+     { Master bank. Handles all aircraft and environmental audio.                 }
+      xplm_MasterBank                          = 0
+ 
+     { Radio bank. Handles COM1/COM2/GND/Pilot/Copilot.                           }
+     ,xplm_RadioBank                           = 1
+ 
+   );
+   PXPLMBankID = ^XPLMBankID;
+
+
+   {
+    XPLMGetFMODStudio
+    
+    Get a handle to the FMOD Studio, allowing you to load/process whatever else
+    you need. This also gives access to the underlying system via
+    FMOD::Studio::System::getCoreSystem() / FMOD_Studio_System_GetCoreSystem()
+    . When a separate output device is being used for the radio, this will
+    always return the FMOD::Studio that is running the environment output, as
+    before. If you want to specifically target the headset output device, you
+    can obtain that FMOD::Studio by getting one of the radio-specific output
+    channelgroups and using the getSystem() call on that.
+   }
+   FUNCTION XPLMGetFMODStudio: PFMOD_STUDIO_SYSTEM;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetFMODChannelGroup
+    
+    Get a reference to a particular channel group - that is, an output channel.
+    See the table above for values.
+   }
+   FUNCTION XPLMGetFMODChannelGroup(
+                                        audioType           : XPLMAudioBus) : PFMOD_CHANNELGROUP;
+    cdecl; external XPLM_DLL;
+
+
+   {
+    XPLMPCMComplete_f
+    
+    If you use XPLMPlayPCMOnBus() you may use this optional callback to find
+    out when the FMOD::Channel is complete, if you need to deallocate memory
+    for example.
+   }
+TYPE
+     XPLMPCMComplete_f = PROCEDURE(
+                                    inRefcon            : pointer;
+                                    status              : FMOD_RESULT); cdecl;
+
+   {
+    XPLMPlayPCMOnBus
+    
+    Play an in-memory audio buffer on a given audio bus. The resulting FMOD
+    channel is returned. PAY ATTENTION TO THE CALLBACK - when the sample
+    completes or is stopped by X-Plane, the channel will go away. It's up to
+    you to listen for the callback and invalidate any copy of the channel
+    pointer you have lying around. The callback is optional because if you have
+    no intention of interacting with the sound after it's launched, then you
+    don't need to keep the channel pointer at all. The sound is not started
+    instantly. Instead, it will be started the next time X-Plane refreshes the
+    sound system, typically at the start of the next frame. This allows you to
+    set the initial position for the sound, if required. The callback will be
+    called on the main thread, and will be called only once per sound. If the
+    call fails and you provide a callback function, you will get a callback
+    with an FMOD status code.
+   }
+   FUNCTION XPLMPlayPCMOnBus(
+                                        audioBuffer         : pointer;
+                                        bufferSize          : uint32_t;
+                                        soundFormat         : FMOD_SOUND_FORMAT;
+                                        freqHz              : Integer;
+                                        numChannels         : Integer;
+                                        loop                : Integer;
+                                        audioType           : XPLMAudioBus;
+                                        inCallback          : XPLMPCMComplete_f;
+                                        inRefcon            : pointer) : PFMOD_CHANNEL;    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMStopAudio
+    
+    Stop playing an active FMOD channel. If you defined a completion callback,
+    this will be called. After this, the FMOD::Channel* will no longer be valid
+    and must not be used in any future calls.
+   }
+   FUNCTION XPLMStopAudio(
+                                        fmod_channel        : PFMOD_CHANNEL) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAudioPosition
+    
+    Move the given audio channel (i.e. a single sound) to a specific location
+    in local co-ordinates. This will set the sound to 3D if it is not already.
+   }
+   FUNCTION XPLMSetAudioPosition(
+                                        fmod_channel        : PFMOD_CHANNEL;
+                                        position            : PFMOD_VECTOR;
+                                        velocity            : PFMOD_VECTOR) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAudioFadeDistance
+    
+    Set the minimum and maximum fade distances for a given sound. This is
+    highly unlikely to be 0 - please see
+    https://documentation.help/FMOD-Studio-API/FMOD_Sound_Set3DMinMaxDistance.html
+    for full details. This will set the sound to 3D if it is not already. You
+    can set a 3D sound back to 2D by passing negative values for both min amd
+    max.
+   }
+   FUNCTION XPLMSetAudioFadeDistance(
+                                        fmod_channel        : PFMOD_CHANNEL;
+                                        min_fade_distance   : Single;
+                                        max_fade_distance   : Single) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAudioVolume
+    
+    Set the current volume of an active FMOD channel. This should be used to
+    handle changes in the audio source volume, not for fading with distance.
+    Values from 0 to 1 are normal, above 1 can be used to artificially amplify
+    a sound.
+   }
+   FUNCTION XPLMSetAudioVolume(
+                                        fmod_channel        : PFMOD_CHANNEL;
+                                        source_volume       : Single) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAudioPitch
+    
+    Change the current pitch of an active FMOD channel.
+   }
+   FUNCTION XPLMSetAudioPitch(
+                                        fmod_channel        : PFMOD_CHANNEL;
+                                        audio_pitch_hz      : Single) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSetAudioCone
+    
+    Set a directional cone for an active FMOD channel. The orientation vector
+    is in local coordinates. This will set the sound to 3D if it is not
+    already.
+   }
+   FUNCTION XPLMSetAudioCone(
+                                        fmod_channel        : PFMOD_CHANNEL;
+                                        inside_angle        : Single;
+                                        outside_angle       : Single;
+                                        outside_volume      : Single;
+                                        orientation         : PFMOD_VECTOR) : FMOD_RESULT;
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM400}
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMUtilities.pas b/SDK/Delphi/XPLM/XPLMUtilities.pas
new file mode 100644
index 0000000..cd5a499
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMUtilities.pas
@@ -0,0 +1,971 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMUtilities;
+INTERFACE
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * FILE UTILITIES
+ ___________________________________________________________________________}
+{
+   The XPLMUtilities file APIs provide some basic file and path functions for
+   use with X-Plane.
+   
+   Directory Separators
+   --------------------
+   
+   The XPLM has two modes it can work in:
+   
+    * X-Plane native paths: all paths are UTF8 strings, using the unix forward
+      slash (/) as the directory separating character.  In native path mode,
+      you use the same path format for all three operating systems.
+   
+    * Legacy OS paths: the directroy separator is \ for Windows, : for OS X,
+      and / for Linux; OS paths are encoded in MacRoman for OS X using legacy
+      HFS conventions, use the application code page for multi-byte encoding
+      on Unix using DOS path conventions, and use UTF-8 for Linux.
+   
+   While legacy OS paths are the default, we strongly encourage you to opt in
+   to native paths using the XPLMEnableFeature API.
+   
+    * All OS X plugins should enable native paths all of the time; if you do
+      not do this, you will have to convert all paths back from HFS to Unix
+      (and deal with MacRoman) - code written using native paths and the C
+      file APIs "just works" on OS X.
+   
+    * For Linux plugins, there is no difference between the two encodings.
+   
+    * Windows plugins will need to convert the UTF8 file paths to UTF16 for
+      use with the "wide" APIs. While it might seem tempting to stick with
+      legacy OS paths (and just use the "ANSI" Windows APIs), X-Plane is fully
+      unicode-capable, and will often be installed in paths where the user's
+      directories have no ACP encoding.
+   
+   Full and Relative Paths
+   -----------------------
+   
+   Some of these APIs use full paths, but others use paths relative to the
+   user's X-Plane installation. This is documented on a per-API basis.
+}
+
+
+{$IFDEF XPLM200}
+   {
+    XPLMDataFileType
+    
+    These enums define types of data files you can load or unload using the
+    SDK.
+   }
+TYPE
+   XPLMDataFileType = (
+     { A situation (.sit) file, which starts off a flight in a given              }
+     { configuration.                                                             }
+      xplm_DataFile_Situation                  = 1
+ 
+     { A situation movie (.smo) file, which replays a past flight.                }
+     ,xplm_DataFile_ReplayMovie                = 2
+ 
+   );
+   PXPLMDataFileType = ^XPLMDataFileType;
+{$ENDIF XPLM200}
+
+   {
+    XPLMGetSystemPath
+    
+    This function returns the full path to the X-System folder. Note that this
+    is a directory path, so it ends in a trailing : or / .
+    
+    The buffer you pass should be at least 512 characters long.  The path is
+    returned using the current native or OS path conventions.
+   }
+   PROCEDURE XPLMGetSystemPath(
+                                        outSystemPath       : XPLMString);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetPrefsPath
+    
+    This routine returns a full path to a file that is within X-Plane's
+    preferences directory. (You should remove the file name back to the last
+    directory separator to get the preferences directory using
+    XPLMExtractFileAndPath).
+    
+    The buffer you pass should be at least 512 characters long.  The path is
+    returned using the current native or OS path conventions.
+   }
+   PROCEDURE XPLMGetPrefsPath(
+                                        outPrefsPath        : XPLMString);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDirectorySeparator
+    
+    This routine returns a string with one char and a null terminator that is
+    the directory separator for the current platform. This allows you to write
+    code that concatenates directory paths without having to #ifdef for
+    platform. The character returned will reflect the current file path mode.
+   }
+   FUNCTION XPLMGetDirectorySeparator: XPLMString;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMExtractFileAndPath
+    
+    Given a full path to a file, this routine separates the path from the file.
+    If the path is a partial directory (e.g. ends in : or / ) the trailing
+    directory separator is removed. This routine works in-place; a pointer to
+    the file part of the buffer is returned; the original buffer still starts
+    with the path and is null terminated with no trailing separator.
+   }
+   FUNCTION XPLMExtractFileAndPath(
+                                        inFullPath          : XPLMString) : XPLMString;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetDirectoryContents
+    
+    This routine returns a list of files in a directory (specified by a full
+    path, no trailing : or / ). The output is returned as a list of NULL
+    terminated strings. An index array (if specified) is filled with pointers
+    into the strings. The last file is indicated by a zero-length string (and
+    NULL in the indices). This routine will return 1 if you had capacity for
+    all files or 0 if you did not. You can also skip a given number of files.
+    
+     * inDirectoryPath - a null terminated C string containing the full path to
+       the directory with no trailing directory char.
+    
+     * inFirstReturn - the zero-based index of the first file in the directory
+       to return. (Usually zero to fetch all in one pass.)
+    
+     * outFileNames - a buffer to receive a series of sequential null
+       terminated C-string file names. A zero-length C string will be appended
+       to the very end.
+    
+     * inFileNameBufSize - the size of the file name buffer in bytes.
+    
+     * outIndices - a pointer to an array of character pointers that will
+       become an index into the directory. The last file will be followed by a
+       NULL value. Pass NULL if you do not want indexing information.
+    
+     * inIndexCount - the max size of the index in entries.
+    
+     * outTotalFiles - if not NULL, this is filled in with the number of files
+       in the directory.
+    
+     * outReturnedFiles - if not NULL, the number of files returned by this
+       iteration.
+    
+    Return value: 1 if all info could be returned, 0 if there was a buffer
+    overrun.
+    
+    WARNING: Before X-Plane 7 this routine did not properly iterate through
+    directories. If X-Plane
+    6 compatibility is needed, use your own code to iterate directories.
+   }
+   FUNCTION XPLMGetDirectoryContents(
+                                        inDirectoryPath     : XPLMString;
+                                        inFirstReturn       : Integer;
+                                        outFileNames        : XPLMString;
+                                        inFileNameBufSize   : Integer;
+                                        outIndices          : PXPLMString;    { Can be nil }
+                                        inIndexCount        : Integer;
+                                        outTotalFiles       : PInteger;    { Can be nil }
+                                        outReturnedFiles    : PInteger) : Integer;    { Can be nil }
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM200}
+   {
+    XPLMLoadDataFile
+    
+    Loads a data file of a given type. Paths must be relative to the X-System
+    folder. To clear the replay, pass a NULL file name (this is only valid with
+    replay movies, not sit files).
+   }
+   FUNCTION XPLMLoadDataFile(
+                                        inFileType          : XPLMDataFileType;
+                                        inFilePath          : XPLMString) : Integer;    { Can be nil }
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+   {
+    XPLMSaveDataFile
+    
+    Saves the current situation or replay; paths are relative to the X-System
+    folder.
+   }
+   FUNCTION XPLMSaveDataFile(
+                                        inFileType          : XPLMDataFileType;
+                                        inFilePath          : XPLMString) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+{___________________________________________________________________________
+ * X-PLANE MISC
+ ___________________________________________________________________________}
+
+   {
+    XPLMHostApplicationID
+    
+    While the plug-in SDK is only accessible to plugins running inside X-Plane,
+    the original authors considered extending the API to other applications
+    that shared basic infrastructure with X-Plane. These enumerations are
+    hold-overs from that original roadmap; all values other than X-Plane are
+    deprecated. Your plugin should never need this enumeration.
+   }
+TYPE
+   XPLMHostApplicationID = (
+      xplm_Host_Unknown                        = 0
+ 
+     ,xplm_Host_XPlane                         = 1
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_PlaneMaker                     = 2
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_WorldMaker                     = 3
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_Briefer                        = 4
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_PartMaker                      = 5
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_YoungsMod                      = 6
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_XAuto                          = 7
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_Xavion                         = 8
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_Control_Pad                    = 9
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_PFD_Map                        = 10
+{$ENDIF XPLM_DEPRECATED}
+ 
+{$IFDEF XPLM_DEPRECATED}
+     ,xplm_Host_RADAR                          = 11
+{$ENDIF XPLM_DEPRECATED}
+ 
+   );
+   PXPLMHostApplicationID = ^XPLMHostApplicationID;
+
+   {
+    XPLMLanguageCode
+    
+    These enums define what language the sim is running in. These enumerations
+    do not imply that the sim can or does run in all of these languages; they
+    simply provide a known encoding in the event that a given sim version is
+    localized to a certain language.
+   }
+   XPLMLanguageCode = (
+      xplm_Language_Unknown                    = 0
+ 
+     ,xplm_Language_English                    = 1
+ 
+     ,xplm_Language_French                     = 2
+ 
+     ,xplm_Language_German                     = 3
+ 
+     ,xplm_Language_Italian                    = 4
+ 
+     ,xplm_Language_Spanish                    = 5
+ 
+     ,xplm_Language_Korean                     = 6
+ 
+{$IFDEF XPLM200}
+     ,xplm_Language_Russian                    = 7
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM200}
+     ,xplm_Language_Greek                      = 8
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM200}
+     ,xplm_Language_Japanese                   = 9
+{$ENDIF XPLM200}
+ 
+{$IFDEF XPLM300}
+     ,xplm_Language_Chinese                    = 10
+{$ENDIF XPLM300}
+ 
+{$IFDEF XPLM400}
+     ,xplm_Language_Ukrainian                  = 11
+{$ENDIF XPLM400}
+ 
+   );
+   PXPLMLanguageCode = ^XPLMLanguageCode;
+
+{$IFDEF XPLM200}
+   {
+    XPLMError_f
+    
+    An XPLM error callback is a function that you provide to receive debugging
+    information from the plugin SDK. See XPLMSetErrorCallback for more
+    information. NOTE: for the sake of debugging, your error callback will be
+    called even if your plugin is not enabled, allowing you to receive debug
+    info in your XPluginStart and XPluginStop callbacks. To avoid causing logic
+    errors in the management code, do not call any other plugin routines from
+    your error callback - it is only meant for catching errors in the
+    debugging.
+   }
+TYPE
+     XPLMError_f = PROCEDURE(
+                                    inMessage           : XPLMString); cdecl;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM_DEPRECATED}
+   {
+    XPLMInitialized
+    
+    Deprecated: This function returns 1 if X-Plane has properly initialized the
+    plug-in system. If this routine returns 0, many XPLM functions will not
+    work.
+    
+    NOTE: because plugins are always called from within the XPLM, there is no
+    need to check for initialization; it will always return 1.  This routine is
+    deprecated - you do not need to check it before continuing within your
+    plugin.
+   }
+   FUNCTION XPLMInitialized: Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM_DEPRECATED}
+
+   {
+    XPLMGetVersions
+    
+    This routine returns the revision of both X-Plane and the XPLM DLL. All
+    versions are at least three-digit decimal numbers (e.g. 606 for version
+    6.06 of X-Plane); the current revision of the XPLM is 400 (4.00). This
+    routine also returns the host ID of the app running us.
+    
+    The most common use of this routine is to special-case around X-Plane
+    version-specific behavior.
+   }
+   PROCEDURE XPLMGetVersions(
+                                        outXPlaneVersion    : PInteger;
+                                        outXPLMVersion      : PInteger;
+                                        outHostID           : PXPLMHostApplicationID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetLanguage
+    
+    This routine returns the langauge the sim is running in.
+   }
+   FUNCTION XPLMGetLanguage: XPLMLanguageCode;
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM200}
+   {
+    XPLMFindSymbol
+    
+    This routine will attempt to find the symbol passed in the inString
+    parameter. If the symbol is found a pointer the function is returned,
+    othewise the function will return NULL.
+    
+    You can use XPLMFindSymbol to utilize newer SDK API features without
+    requiring newer versions of the SDK (and X-Plane) as your minimum X-Plane
+    version as follows:
+    
+     * Define the XPLMnnn macro to the minimum required XPLM version you will
+       ship with (e.g. XPLM210 for X-Plane 10 compatibility).
+    
+     * Use XPLMGetVersions and XPLMFindSymbol to detect that the host sim is
+       new enough to use new functions and resolve function pointers.
+    
+     * Conditionally use the new functions if and only if XPLMFindSymbol only
+       returns a non- NULL pointer.
+    
+    Warning: you should always check the XPLM API version as well as the
+    results of XPLMFindSymbol to determine if funtionality is safe to use.
+    
+    To use functionality via XPLMFindSymbol you will need to copy your own
+    definitions of the X-Plane API prototypes and cast the returned pointer to
+    the correct type.
+   }
+   FUNCTION XPLMFindSymbol(
+                                        inString            : XPLMString) : pointer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+{$IFDEF XPLM200}
+   {
+    XPLMSetErrorCallback
+    
+    XPLMSetErrorCallback installs an error-reporting callback for your plugin.
+    Normally the plugin system performs minimum diagnostics to maximize
+    performance. When you install an error callback, you will receive calls due
+    to certain plugin errors, such as passing bad parameters or incorrect data.
+    
+    Important: the error callback determines *programming* errors, e.g. bad API
+    parameters. Every error that is returned by the error callback represents a
+    mistake in your plugin that you should fix. Error callbacks are not used to
+    report expected run-time problems (e.g. disk I/O errors).
+    
+    The intention is for you to install the error callback during debug
+    sections and put a break-point inside your callback. This will cause you to
+    break into the debugger from within the SDK at the point in your plugin
+    where you made an illegal call.
+    
+    Installing an error callback may activate error checking code that would
+    not normally run, and this may adversely affect performance, so do not
+    leave error callbacks installed in shipping plugins. Since the only useful
+    response to an error is to change code, error callbacks are not useful "in
+    the field".
+   }
+   PROCEDURE XPLMSetErrorCallback(
+                                        inCallback          : XPLMError_f);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM200}
+
+   {
+    XPLMDebugString
+    
+    This routine outputs a C-style string to the Log.txt file. The file is
+    immediately flushed so you will not lose data. (This does cause a
+    performance penalty.)
+    
+    Please do *not* leave routine diagnostic logging enabled in your shipping
+    plugin. The X-Plane Log file is shared by X-Plane and every plugin in the
+    system, and plugins that (when functioning normally) print verbose log
+    output make it difficult for developers to find error conditions from other
+    parts of the system.
+   }
+   PROCEDURE XPLMDebugString(
+                                        inString            : XPLMString);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMSpeakString
+    
+    This function displays the string in a translucent overlay over the current
+    display and also speaks the string if text-to-speech is enabled. The string
+    is spoken asynchronously, this function returns immediately. This function
+    may not speak or print depending on user preferences.
+   }
+   PROCEDURE XPLMSpeakString(
+                                        inString            : XPLMString);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMGetVirtualKeyDescription
+    
+    Given a virtual key code (as defined in XPLMDefs.h) this routine returns a
+    human-readable string describing the character. This routine is provided
+    for showing users what keyboard mappings they have set up. The string may
+    read 'unknown' or be a blank or NULL string if the virtual key is unknown.
+   }
+   FUNCTION XPLMGetVirtualKeyDescription(
+                                        inVirtualKey        : XPLMChar) : XPLMString;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMReloadScenery
+    
+    XPLMReloadScenery reloads the current set of scenery. You can use this
+    function in two typical ways: simply call it to reload the scenery, picking
+    up any new installed scenery, .env files, etc. from disk. Or, change the
+    lat/ref and lon/ref datarefs and then call this function to shift the
+    scenery environment.  This routine is equivalent to picking "reload
+    scenery" from the developer menu.
+   }
+   PROCEDURE XPLMReloadScenery;
+    cdecl; external XPLM_DLL;
+
+{$IFDEF XPLM200}
+{___________________________________________________________________________
+ * X-PLANE COMMAND MANAGEMENT
+ ___________________________________________________________________________}
+{
+   The command management APIs let plugins interact with the command-system in
+   X-Plane, the abstraction behind keyboard presses and joystick buttons. This
+   API lets you create new commands and modify the behavior (or get
+   notification) of existing ones.
+   
+   X-Plane Command Phases
+   ----------------------
+   
+   X-Plane commands are not instantaneous; they operate over a duration.
+   (Think of a joystick button press - you can press, hold down, and then
+   release the joystick button; X-Plane commands model this entire process.)
+   
+   An X-Plane command consists of three phases: a beginning, continuous
+   repetition, and an ending. The command may be repeated zero times in its
+   duration, followed by one command ending. Command begin and end messges are
+   balanced, but a command may be bound to more than one event source (e.g. a
+   keyboard key and a joystick button), in which case you may receive a second
+   begin during before any end).
+   
+   When you issue commands in the plugin system, you *must* balance every call
+   to XPLMCommandBegin with a call to XPLMCommandEnd with the same command
+   reference.
+   
+   Command Behavior Modification
+   -----------------------------
+   
+   You can register a callback to handle a command either before or after
+   X-Plane does; if you receive the command before X-Plane you have the option
+   to either let X-Plane handle the command or hide the command from X-Plane.
+   This lets plugins both augment commands and replace them.
+   
+   If you register for an existing command, be sure that you are *consistent*
+   in letting X-Plane handle or not handle the command; you are responsible
+   for passing a *balanced* number of begin and end messages to X-Plane. (E.g.
+   it is not legal to pass all the begin messages to X-Plane but hide all the
+   end messages).
+}
+
+
+   {
+    XPLMCommandPhase
+    
+    The phases of a command.
+   }
+TYPE
+   XPLMCommandPhase = (
+     { The command is being started.                                              }
+      xplm_CommandBegin                        = 0
+ 
+     { The command is continuing to execute.                                      }
+     ,xplm_CommandContinue                     = 1
+ 
+     { The command has ended.                                                     }
+     ,xplm_CommandEnd                          = 2
+ 
+   );
+   PXPLMCommandPhase = ^XPLMCommandPhase;
+
+   {
+    XPLMCommandRef
+    
+    A command ref is an opaque identifier for an X-Plane command. Command
+    references stay the same for the life of your plugin but not between
+    executions of X-Plane. Command refs are used to execute commands, create
+    commands, and create callbacks for particular commands.
+    
+    Note that a command is not "owned" by a particular plugin. Since many
+    plugins may participate in a command's execution, the command does not go
+    away if the plugin that created it is unloaded.
+   }
+   XPLMCommandRef = pointer;
+   PXPLMCommandRef = ^XPLMCommandRef;
+
+   {
+    XPLMCommandCallback_f
+    
+    A command callback is a function in your plugin that is called when a
+    command is pressed. Your callback receives the command reference for the
+    particular command, the phase of the command that is executing, and a
+    reference pointer that you specify when registering the callback.
+    
+    Your command handler should return 1 to let processing of the command
+    continue to other plugins and X-Plane, or 0 to halt processing, potentially
+    bypassing X-Plane code.
+   }
+     XPLMCommandCallback_f = FUNCTION(
+                                    inCommand           : XPLMCommandRef;
+                                    inPhase             : XPLMCommandPhase;
+                                    inRefcon            : pointer) : Integer; cdecl;
+
+   {
+    XPLMFindCommand
+    
+    XPLMFindCommand looks up a command by name, and returns its command
+    reference or NULL if the command does not exist.
+   }
+   FUNCTION XPLMFindCommand(
+                                        inName              : XPLMString) : XPLMCommandRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandBegin
+    
+    XPLMCommandBegin starts the execution of a command, specified by its
+    command reference. The command is "held down" until XPLMCommandEnd is
+    called.  You must balance each XPLMCommandBegin call with an XPLMCommandEnd
+    call.
+   }
+   PROCEDURE XPLMCommandBegin(
+                                        inCommand           : XPLMCommandRef);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandEnd
+    
+    XPLMCommandEnd ends the execution of a given command that was started with
+    XPLMCommandBegin.  You must not issue XPLMCommandEnd for a command you did
+    not begin.
+   }
+   PROCEDURE XPLMCommandEnd(
+                                        inCommand           : XPLMCommandRef);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandOnce
+    
+    This executes a given command momentarily, that is, the command begins and
+    ends immediately. This is the equivalent of calling XPLMCommandBegin() and
+    XPLMCommandEnd() back to back.
+   }
+   PROCEDURE XPLMCommandOnce(
+                                        inCommand           : XPLMCommandRef);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCreateCommand
+    
+    XPLMCreateCommand creates a new command for a given string. If the command
+    already exists, the existing command reference is returned. The description
+    may appear in user interface contexts, such as the joystick configuration
+    screen.
+   }
+   FUNCTION XPLMCreateCommand(
+                                        inName              : XPLMString;
+                                        inDescription       : XPLMString) : XPLMCommandRef;
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMRegisterCommandHandler
+    
+    XPLMRegisterCommandHandler registers a callback to be called when a command
+    is executed. You provide a callback with a reference pointer.
+    
+    If inBefore is true, your command handler callback will be executed before
+    X-Plane executes the command, and returning 0 from your callback will
+    disable X-Plane's processing of the command. If inBefore is false, your
+    callback will run after X-Plane. (You can register a single callback both
+    before and after a command.)
+   }
+   PROCEDURE XPLMRegisterCommandHandler(
+                                        inComand            : XPLMCommandRef;
+                                        inHandler           : XPLMCommandCallback_f;
+                                        inBefore            : Integer;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMUnregisterCommandHandler
+    
+    XPLMUnregisterCommandHandler removes a command callback registered with
+    XPLMRegisterCommandHandler.
+   }
+   PROCEDURE XPLMUnregisterCommandHandler(
+                                        inComand            : XPLMCommandRef;
+                                        inHandler           : XPLMCommandCallback_f;
+                                        inBefore            : Integer;
+                                        inRefcon            : pointer);
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM200}
+{$IFDEF XPLM_DEPRECATED}
+{___________________________________________________________________________
+ * X-PLANE USER INTERACTION
+ ___________________________________________________________________________}
+{
+   WARNING: The legacy user interaction API is deprecated; while it was the
+   only way to run commands in X-Plane 6,7 and 8, it is obsolete, and was
+   replaced by the command system API in X-Plane 9. You should not use this
+   API; replace any of the calls below with XPLMCommand invocations based on
+   persistent command strings. The documentation that follows is for historic
+   reference only.
+   
+   The legacy user interaction APIs let you simulate commands the user can do
+   with a joystick, keyboard etc. Note that it is generally safer for future
+   compatibility to use one of these commands than to manipulate the
+   underlying sim data.
+}
+
+
+   {
+    XPLMCommandKeyID
+    
+    These enums represent all the keystrokes available within X-Plane. They can
+    be sent to X-Plane directly. For example, you can reverse thrust using
+    these enumerations.
+   }
+TYPE
+   XPLMCommandKeyID = (
+          xplm_key_pause=0,
+          xplm_key_revthrust,
+          xplm_key_jettison,
+          xplm_key_brakesreg,
+          xplm_key_brakesmax,
+          xplm_key_gear,
+          xplm_key_timedn,
+          xplm_key_timeup,
+          xplm_key_fadec,
+          xplm_key_otto_dis,
+          xplm_key_otto_atr,
+          xplm_key_otto_asi,
+          xplm_key_otto_hdg,
+          xplm_key_otto_gps,
+          xplm_key_otto_lev,
+          xplm_key_otto_hnav,
+          xplm_key_otto_alt,
+          xplm_key_otto_vvi,
+          xplm_key_otto_vnav,
+          xplm_key_otto_nav1,
+          xplm_key_otto_nav2,
+          xplm_key_targ_dn,
+          xplm_key_targ_up,
+          xplm_key_hdgdn,
+          xplm_key_hdgup,
+          xplm_key_barodn,
+          xplm_key_baroup,
+          xplm_key_obs1dn,
+          xplm_key_obs1up,
+          xplm_key_obs2dn,
+          xplm_key_obs2up,
+          xplm_key_com1_1,
+          xplm_key_com1_2,
+          xplm_key_com1_3,
+          xplm_key_com1_4,
+          xplm_key_nav1_1,
+          xplm_key_nav1_2,
+          xplm_key_nav1_3,
+          xplm_key_nav1_4,
+          xplm_key_com2_1,
+          xplm_key_com2_2,
+          xplm_key_com2_3,
+          xplm_key_com2_4,
+          xplm_key_nav2_1,
+          xplm_key_nav2_2,
+          xplm_key_nav2_3,
+          xplm_key_nav2_4,
+          xplm_key_adf_1,
+          xplm_key_adf_2,
+          xplm_key_adf_3,
+          xplm_key_adf_4,
+          xplm_key_adf_5,
+          xplm_key_adf_6,
+          xplm_key_transpon_1,
+          xplm_key_transpon_2,
+          xplm_key_transpon_3,
+          xplm_key_transpon_4,
+          xplm_key_transpon_5,
+          xplm_key_transpon_6,
+          xplm_key_transpon_7,
+          xplm_key_transpon_8,
+          xplm_key_flapsup,
+          xplm_key_flapsdn,
+          xplm_key_cheatoff,
+          xplm_key_cheaton,
+          xplm_key_sbrkoff,
+          xplm_key_sbrkon,
+          xplm_key_ailtrimL,
+          xplm_key_ailtrimR,
+          xplm_key_rudtrimL,
+          xplm_key_rudtrimR,
+          xplm_key_elvtrimD,
+          xplm_key_elvtrimU,
+          xplm_key_forward,
+          xplm_key_down,
+          xplm_key_left,
+          xplm_key_right,
+          xplm_key_back,
+          xplm_key_tower,
+          xplm_key_runway,
+          xplm_key_chase,
+          xplm_key_free1,
+          xplm_key_free2,
+          xplm_key_spot,
+          xplm_key_fullscrn1,
+          xplm_key_fullscrn2,
+          xplm_key_tanspan,
+          xplm_key_smoke,
+          xplm_key_map,
+          xplm_key_zoomin,
+          xplm_key_zoomout,
+          xplm_key_cycledump,
+          xplm_key_replay,
+          xplm_key_tranID,
+          xplm_key_max
+   );
+   PXPLMCommandKeyID = ^XPLMCommandKeyID;
+
+   {
+    XPLMCommandButtonID
+    
+    These are enumerations for all of the things you can do with a joystick
+    button in X-Plane. They currently match the buttons menu in the equipment
+    setup dialog, but these enums will be stable even if they change in
+    X-Plane.
+   }
+   XPLMCommandButtonID = (
+          xplm_joy_nothing=0,
+          xplm_joy_start_all,
+          xplm_joy_start_0,
+          xplm_joy_start_1,
+          xplm_joy_start_2,
+          xplm_joy_start_3,
+          xplm_joy_start_4,
+          xplm_joy_start_5,
+          xplm_joy_start_6,
+          xplm_joy_start_7,
+          xplm_joy_throt_up,
+          xplm_joy_throt_dn,
+          xplm_joy_prop_up,
+          xplm_joy_prop_dn,
+          xplm_joy_mixt_up,
+          xplm_joy_mixt_dn,
+          xplm_joy_carb_tog,
+          xplm_joy_carb_on,
+          xplm_joy_carb_off,
+          xplm_joy_trev,
+          xplm_joy_trm_up,
+          xplm_joy_trm_dn,
+          xplm_joy_rot_trm_up,
+          xplm_joy_rot_trm_dn,
+          xplm_joy_rud_lft,
+          xplm_joy_rud_cntr,
+          xplm_joy_rud_rgt,
+          xplm_joy_ail_lft,
+          xplm_joy_ail_cntr,
+          xplm_joy_ail_rgt,
+          xplm_joy_B_rud_lft,
+          xplm_joy_B_rud_rgt,
+          xplm_joy_look_up,
+          xplm_joy_look_dn,
+          xplm_joy_look_lft,
+          xplm_joy_look_rgt,
+          xplm_joy_glance_l,
+          xplm_joy_glance_r,
+          xplm_joy_v_fnh,
+          xplm_joy_v_fwh,
+          xplm_joy_v_tra,
+          xplm_joy_v_twr,
+          xplm_joy_v_run,
+          xplm_joy_v_cha,
+          xplm_joy_v_fr1,
+          xplm_joy_v_fr2,
+          xplm_joy_v_spo,
+          xplm_joy_flapsup,
+          xplm_joy_flapsdn,
+          xplm_joy_vctswpfwd,
+          xplm_joy_vctswpaft,
+          xplm_joy_gear_tog,
+          xplm_joy_gear_up,
+          xplm_joy_gear_down,
+          xplm_joy_lft_brake,
+          xplm_joy_rgt_brake,
+          xplm_joy_brakesREG,
+          xplm_joy_brakesMAX,
+          xplm_joy_speedbrake,
+          xplm_joy_ott_dis,
+          xplm_joy_ott_atr,
+          xplm_joy_ott_asi,
+          xplm_joy_ott_hdg,
+          xplm_joy_ott_alt,
+          xplm_joy_ott_vvi,
+          xplm_joy_tim_start,
+          xplm_joy_tim_reset,
+          xplm_joy_ecam_up,
+          xplm_joy_ecam_dn,
+          xplm_joy_fadec,
+          xplm_joy_yaw_damp,
+          xplm_joy_art_stab,
+          xplm_joy_chute,
+          xplm_joy_JATO,
+          xplm_joy_arrest,
+          xplm_joy_jettison,
+          xplm_joy_fuel_dump,
+          xplm_joy_puffsmoke,
+          xplm_joy_prerotate,
+          xplm_joy_UL_prerot,
+          xplm_joy_UL_collec,
+          xplm_joy_TOGA,
+          xplm_joy_shutdown,
+          xplm_joy_con_atc,
+          xplm_joy_fail_now,
+          xplm_joy_pause,
+          xplm_joy_rock_up,
+          xplm_joy_rock_dn,
+          xplm_joy_rock_lft,
+          xplm_joy_rock_rgt,
+          xplm_joy_rock_for,
+          xplm_joy_rock_aft,
+          xplm_joy_idle_hilo,
+          xplm_joy_lanlights,
+          xplm_joy_max
+   );
+   PXPLMCommandButtonID = ^XPLMCommandButtonID;
+
+   {
+    XPLMSimulateKeyPress
+    
+    This function simulates a key being pressed for X-Plane. The keystroke goes
+    directly to X-Plane; it is never sent to any plug-ins. However, since this
+    is a raw key stroke it may be mapped by the keys file or enter text into a
+    field.
+    
+    Deprecated: use XPLMCommandOnce
+   }
+   PROCEDURE XPLMSimulateKeyPress(
+                                        inKeyType           : Integer;
+                                        inKey               : Integer);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandKeyStroke
+    
+    This routine simulates a command-key stroke. However, the keys are done by
+    function, not by actual letter, so this function works even if the user has
+    remapped their keyboard. Examples of things you might do with this include
+    pausing the simulator.
+    
+    Deprecated: use XPLMCommandOnce
+   }
+   PROCEDURE XPLMCommandKeyStroke(
+                                        inKey               : XPLMCommandKeyID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandButtonPress
+    
+    This function simulates any of the actions that might be taken by pressing
+    a joystick button. However, this lets you call the command directly rather
+    than having to know which button is mapped where. Important: you must
+    release each button you press. The APIs are separate so that you can 'hold
+    down' a button for a fixed amount of time.
+    
+    Deprecated: use XPLMCommandBegin.
+   }
+   PROCEDURE XPLMCommandButtonPress(
+                                        inButton            : XPLMCommandButtonID);
+    cdecl; external XPLM_DLL;
+
+   {
+    XPLMCommandButtonRelease
+    
+    This function simulates any of the actions that might be taken by pressing
+    a joystick button. See XPLMCommandButtonPress.
+    
+    Deprecated: use XPLMCommandEnd.
+   }
+   PROCEDURE XPLMCommandButtonRelease(
+                                        inButton            : XPLMCommandButtonID);
+    cdecl; external XPLM_DLL;
+
+{$ENDIF XPLM_DEPRECATED}
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Delphi/XPLM/XPLMWeather.pas b/SDK/Delphi/XPLM/XPLMWeather.pas
new file mode 100644
index 0000000..05b761d
--- /dev/null
+++ b/SDK/Delphi/XPLM/XPLMWeather.pas
@@ -0,0 +1,137 @@
+{
+   Copyright 2005-2022 Laminar Research, Sandy Barbour and Ben Supnik All
+   rights reserved.  See license.txt for usage. X-Plane SDK Version: 4.0.0
+}
+
+UNIT XPLMWeather;
+INTERFACE
+{
+   This provides access to the X-Plane 12 enhanced weather system.
+}
+
+USES
+    XPLMDefs;
+   {$A4}
+{___________________________________________________________________________
+ * WEATHER ACCESS
+ ___________________________________________________________________________}
+
+   {
+    XPLMWeatherInfoWinds_t
+   }
+TYPE
+   XPLMWeatherInfoWinds_t = RECORD
+     { Altitude MSL, meters                                                       }
+     alt_msl                  : Single;
+     { Wind speed, meters/sec                                                     }
+     speed                    : Single;
+     { Direction (true)                                                           }
+     direction                : Single;
+     { Gust speed, meters/sec                                                     }
+     gust_speed               : Single;
+     { Shear arc, degrees i.e. 50% of this arc in either direction from base      }
+     shear                    : Single;
+     { Clear-air turbulence ratio                                                 }
+     turbulence               : Single;
+   END;
+   PXPLMWeatherInfoWinds_t = ^XPLMWeatherInfoWinds_t;
+
+   {
+    XPLMWeatherInfoClouds_t
+   }
+   XPLMWeatherInfoClouds_t = RECORD
+     { Cloud type, float enum                                                     }
+     cloud_type               : Single;
+     { Coverage ratio                                                             }
+     coverage                 : Single;
+     { Altitude MSL, meters                                                       }
+     alt_top                  : Single;
+     { Altitude MSL, meters                                                       }
+     alt_base                 : Single;
+   END;
+   PXPLMWeatherInfoClouds_t = ^XPLMWeatherInfoClouds_t;
+
+   {
+    XPLMWeatherInfo_t
+    
+    Basic weather conditions at a specific point.
+   }
+   XPLMWeatherInfo_t = RECORD
+     { The size of the struct.                                                    }
+     structSize               : Integer;
+     { Temperature at the given altitude in Celsius                               }
+     temperature_alt          : Single;
+     { Dewpoint at the given altitude in Celsius                                  }
+     dewpoint_alt             : Single;
+     { Pressure at the given altitude in Pascals                                  }
+     pressure_alt             : Single;
+     { Precipitation rate at the given altitude                                   }
+     precip_rate_alt          : Single;
+     { Wind direction at the given altitude                                       }
+     wind_dir_alt             : Single;
+     { Wind speed at the given altitude, meters/sec                               }
+     wind_spd_alt             : Single;
+     { Turbulence ratio at the given altitude                                     }
+     turbulence_alt           : Single;
+     { Height of water waves in meters                                            }
+     wave_height              : Single;
+     { Length of water waves in meters                                            }
+     wave_length              : Single;
+     { Direction from which water waves are coming                                }
+     wave_dir                 : Integer;
+     { Speed of wave advance in meters/sec                                        }
+     wave_speed               : Single;
+     { Base visibility at 0 altitude, meters                                      }
+     visibility               : Single;
+     { Base precipitation ratio at 0 altitude                                     }
+     precip_rate              : Single;
+     { Climb rate due to thermals, meters/sec                                     }
+     thermal_climb            : Single;
+     { Pressure at 0 altitude in Pascals                                          }
+     pressure_sl              : Single;
+     { Defined wind layers. Not all layers are always defined.                    }
+     wind_layers[13]          : XPLMWeatherInfoWinds_t;
+     { Defined cloud layers. Not all layers are always defined.                   }
+     cloud_layers[3]          : XPLMWeatherInfoClouds_t;
+   END;
+   PXPLMWeatherInfo_t = ^XPLMWeatherInfo_t;
+
+{$IFDEF XPLM400}
+   {
+    XPLMGetMETARForAirport
+    
+    Get the last-downloaded METAR report for an airport by ICAO code. Note that
+    the actual weather at that airport may have evolved significantly since the
+    last downloaded METAR. outMETAR must point to a char buffer of at least 150
+    characters. This call is not intended to be used per-frame. This call does
+    not return the current weather at the airport, and returns an empty string
+    if the system is not in real-weather mode.
+   }
+   PROCEDURE XPLMGetMETARForAirport(
+                                        airport_id          : XPLMString;
+                                        outMETAR            : PXPLMFixedString150_t);
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM400}
+
+{$IFDEF XPLM400}
+   {
+    XPLMGetWeatherAtLocation
+    
+    Get the current weather conditions at a given location. Note that this does
+    not work world-wide, only within the surrounding region. Return 1 if
+    detailed weather (i.e. an airport-specific METAR) was found, 0 if not. In
+    both cases, the structure will contain the best data available. This call
+    is not intended to be used per-frame.
+   }
+   FUNCTION XPLMGetWeatherAtLocation(
+                                        latitude            : Real;
+                                        longitude           : Real;
+                                        altitude_m          : Real;
+                                        out_info            : PXPLMWeatherInfo_t) : Integer;
+    cdecl; external XPLM_DLL;
+{$ENDIF XPLM400}
+
+
+IMPLEMENTATION
+
+END.
diff --git a/SDK/Libraries/Lin/XPLM_64.so b/SDK/Libraries/Lin/XPLM_64.so
new file mode 100755
index 0000000..001e6f6
Binary files /dev/null and b/SDK/Libraries/Lin/XPLM_64.so differ
diff --git a/SDK/Libraries/Lin/XPWidgets_64.so b/SDK/Libraries/Lin/XPWidgets_64.so
new file mode 100755
index 0000000..6eaca3c
Binary files /dev/null and b/SDK/Libraries/Lin/XPWidgets_64.so differ
diff --git a/SDK/Libraries/Mac/XPLM.framework/Resources b/SDK/Libraries/Mac/XPLM.framework/Resources
new file mode 120000
index 0000000..953ee36
--- /dev/null
+++ b/SDK/Libraries/Mac/XPLM.framework/Resources
@@ -0,0 +1 @@
+Versions/Current/Resources
\ No newline at end of file
diff --git a/SDK/Libraries/Mac/XPLM.framework/Versions/C/Resources/Info.plist b/SDK/Libraries/Mac/XPLM.framework/Versions/C/Resources/Info.plist
new file mode 100644
index 0000000..53b5610
--- /dev/null
+++ b/SDK/Libraries/Mac/XPLM.framework/Versions/C/Resources/Info.plist
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildMachineOSBuild</key>
+	<string>22C65</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>XPLM</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>14C18</string>
+	<key>DTPlatformName</key>
+	<string>macosx</string>
+	<key>DTPlatformVersion</key>
+	<string>13.1</string>
+	<key>DTSDKBuild</key>
+	<string>22C55</string>
+	<key>DTSDKName</key>
+	<string>macosx13.1</string>
+	<key>DTXcode</key>
+	<string>1420</string>
+	<key>DTXcodeBuild</key>
+	<string>14C18</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.15</string>
+</dict>
+</plist>
diff --git a/SDK/Libraries/Mac/XPLM.framework/Versions/C/XPLM b/SDK/Libraries/Mac/XPLM.framework/Versions/C/XPLM
new file mode 100755
index 0000000..1ea059f
Binary files /dev/null and b/SDK/Libraries/Mac/XPLM.framework/Versions/C/XPLM differ
diff --git a/SDK/Libraries/Mac/XPLM.framework/Versions/C/_CodeSignature/CodeResources b/SDK/Libraries/Mac/XPLM.framework/Versions/C/_CodeSignature/CodeResources
new file mode 100644
index 0000000..1e37a64
--- /dev/null
+++ b/SDK/Libraries/Mac/XPLM.framework/Versions/C/_CodeSignature/CodeResources
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Resources/Info.plist</key>
+		<data>
+		voAQ/IDgQqHZqcOEgtUnY+ZQ4Vo=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Resources/Info.plist</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			cbolIMR2jzM1jeru8QBpXnyfepv6PMzWJfroq2E2Coo=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^Resources/</key>
+		<true/>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^[^/]+$</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/SDK/Libraries/Mac/XPLM.framework/Versions/Current b/SDK/Libraries/Mac/XPLM.framework/Versions/Current
new file mode 120000
index 0000000..96d80cd
--- /dev/null
+++ b/SDK/Libraries/Mac/XPLM.framework/Versions/Current
@@ -0,0 +1 @@
+C
\ No newline at end of file
diff --git a/SDK/Libraries/Mac/XPLM.framework/XPLM b/SDK/Libraries/Mac/XPLM.framework/XPLM
new file mode 120000
index 0000000..ae3cf6c
--- /dev/null
+++ b/SDK/Libraries/Mac/XPLM.framework/XPLM
@@ -0,0 +1 @@
+Versions/Current/XPLM
\ No newline at end of file
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/Resources b/SDK/Libraries/Mac/XPWidgets.framework/Resources
new file mode 120000
index 0000000..953ee36
--- /dev/null
+++ b/SDK/Libraries/Mac/XPWidgets.framework/Resources
@@ -0,0 +1 @@
+Versions/Current/Resources
\ No newline at end of file
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/Resources/Info.plist b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/Resources/Info.plist
new file mode 100644
index 0000000..60487dd
--- /dev/null
+++ b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/Resources/Info.plist
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildMachineOSBuild</key>
+	<string>22C65</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>XPWidgets</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>14C18</string>
+	<key>DTPlatformName</key>
+	<string>macosx</string>
+	<key>DTPlatformVersion</key>
+	<string>13.1</string>
+	<key>DTSDKBuild</key>
+	<string>22C55</string>
+	<key>DTSDKName</key>
+	<string>macosx13.1</string>
+	<key>DTXcode</key>
+	<string>1420</string>
+	<key>DTXcodeBuild</key>
+	<string>14C18</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.15</string>
+</dict>
+</plist>
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/XPWidgets b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/XPWidgets
new file mode 100755
index 0000000..c996c4a
Binary files /dev/null and b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/XPWidgets differ
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/_CodeSignature/CodeResources b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/_CodeSignature/CodeResources
new file mode 100644
index 0000000..cf0809d
--- /dev/null
+++ b/SDK/Libraries/Mac/XPWidgets.framework/Versions/C/_CodeSignature/CodeResources
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Resources/Info.plist</key>
+		<data>
+		SngFRYyYZvFDvj7WlMImI0nWjNQ=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Resources/Info.plist</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			cyPpU9uTChX7rFyoW42moNimK/DK8zmtQ8Wih5q0fz4=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^Resources/</key>
+		<true/>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^[^/]+$</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/Versions/Current b/SDK/Libraries/Mac/XPWidgets.framework/Versions/Current
new file mode 120000
index 0000000..96d80cd
--- /dev/null
+++ b/SDK/Libraries/Mac/XPWidgets.framework/Versions/Current
@@ -0,0 +1 @@
+C
\ No newline at end of file
diff --git a/SDK/Libraries/Mac/XPWidgets.framework/XPWidgets b/SDK/Libraries/Mac/XPWidgets.framework/XPWidgets
new file mode 120000
index 0000000..61477f4
--- /dev/null
+++ b/SDK/Libraries/Mac/XPWidgets.framework/XPWidgets
@@ -0,0 +1 @@
+Versions/Current/XPWidgets
\ No newline at end of file
diff --git a/SDK/Libraries/Win/XPLM_64.lib b/SDK/Libraries/Win/XPLM_64.lib
new file mode 100644
index 0000000..090ed41
Binary files /dev/null and b/SDK/Libraries/Win/XPLM_64.lib differ
diff --git a/SDK/Libraries/Win/XPWidgets_64.lib b/SDK/Libraries/Win/XPWidgets_64.lib
new file mode 100644
index 0000000..53c55d6
Binary files /dev/null and b/SDK/Libraries/Win/XPWidgets_64.lib differ
diff --git a/SDK/README.txt b/SDK/README.txt
new file mode 100644
index 0000000..122e3df
--- /dev/null
+++ b/SDK/README.txt
@@ -0,0 +1,253 @@
+-------------------------------------------------------------------------------
+                              THE X-PLANE PLUGIN SDK
+-------------------------------------------------------------------------------
+
+This download contains the files necessary to build plugins for X-Plane.  The 
+X-Plane plugin website is:
+
+https://developer.x-plane.com/sdk/
+
+The website contains full documentation on the SDK including tech notes, sample
+plugins, sample code, contact information, and links to the latest versions of
+this SDK.
+
+-------------------------------------------------------------------------------
+                                  SDK FILES
+-------------------------------------------------------------------------------
+
+license.txt	Copyright information for this download.
+README.txt	This document
+CHeaders	Header files for compiling C/C++ plugins
+Delphi		Interfaces for compiling Pascal plugins
+Libraries	Import libraries for linking on Windows
+            and frameworks for linking on Mac.
+
+Note: there are no import/link-time libraries for Linux; on Linux, plugins
+simply leave SDK symbols undefined and they are discovered at runtime.  The 
+SDK website explains this process in more detail.
+
+-------------------------------------------------------------------------------
+                              RELEASE NOTES
+-------------------------------------------------------------------------------
+
+This section contains per-release notes for the history of the X-Plane SDK.
+
+X-Plane SDK Release 4.1.1 10/10/2024
+
+This is a bug fix to the SDK itself; the dylib link paths on the included
+XPLM and XPWidgets frameworks now contain paths compatible with all versions
+of X-Plane and not just X-Plane 12.1.0 and newer. Fixes XPD-16057 and 
+includes doc clarification for sound callbacks.
+
+X-Plane SDK Release 4.1.0 4/10/2024
+
+The 4.1.0 SDK includes two new sets of APIs:
+
+ - XPLMAvionics has new APIs to create custom plugin-driven glass displays,
+   as well as extended callbacks for overriding the existing displays.
+
+ - XPLMNavigation has new APIs for interacting with the FMS and its flight-
+   plans.
+
+This version of the SDK requires X-Plane 12.1.0 or newer.
+
+X-Plane SDK Release 4.0.1 3/16/2023
+
+The 4.0.1 SDK fixes the XPLMSound.h header, which contained invalid C code
+(C++ struct definitons for FMOD_VECTOR and FMOD_ enums.)
+
+X-Plane SDK Release 4.0.0 3/8/2023
+
+The 4.0.0 SDK adds support for ARM64 Macs.  The 4.0 SDK is supported by X-Plane
+12.04 (but can be used with X-Plane 12.00 if not using the weather, sound or 
+dataref introspection APIs). New features:
+
+ - M1/ARM64 support for Mac
+ - Avionics display callbacks provide direct drawing to avionic "devices"
+ - New XPLMSound API
+ - New XPLMWeather API
+ - New dataref APIs to get the set of all datarefs programmatically and be 
+   notified of new datarefs ("introspection").  
+
+X-Plane SDK Release 3.0.2 4/29/2020
+
+The SDK 3.0.2 adds the modern 3-d drawing callback for interoperability with
+Metal and Vulkan, and deprecates most older drawing callbacks.
+
+X-Plane SDK Release 3.0.1 3/5/2018
+
+The SDK 3.0.1 API adds new messages and APIs to support VR.
+
+X-Plane SDK Release 3.0.0 11/2/7/2017
+
+The SDK 3.0 API supports new features and new packaging for plugins. The 3.0
+SDK requires X-Plane 11.0 or newer. New features include:
+
+ - Display APIs to match X-Plane 11's UI.
+ - New map APIs. Legacy 2-d map draw callbacks are deprecated.
+ - Aircraft-plugins get their own menu
+ - Aircraft placement by lat-lon-elevation.
+ - Magnetic variation queries
+ - Chinese language support
+ - New instancing API
+
+The 3.0 SDK supports a new plugin packaging schema:
+
+    <plugin name>/<ABI>/<plugin name>.xpl
+
+where ABI is one of mac_x64, win_x64 or lin_x64. The new schema is preferred,
+so you can pack a version of your plugin that requires 3.0 with this scheme
+and include a legacy 2.x plugin using hte old scheme for X-Plane 10 
+compatibility.
+
+Please use the new scheme where possible - having a unique file name for each
+DLL makes crash reports easier to read and triage.
+
+The 3.0 SDK drops support for 32-bit plugins; if you need to ship a 32-bit 
+plugin for 32-bit X-Plane 10, shipping using two schemes and two binaries may
+be the best option.
+
+X-Plane SDK Release 2.1.3 11/14/13
+
+Fixed XPC Wrappers to use int and intptr_t instead of long.  This fixes
+crashes for plugins on 64-bit Windows.
+
+X-Plane SDK Release 2.1.2 RC2 1/15/13
+
+Removed headers from frameworks, as they don't work; updated README.
+
+X-Plane SDK Release 2.1.2 RC1 1/12/13
+
+The 2.1.2 SDK adds frameworks for the XPLM and XPWidgets; Mac developers
+can link directly against these frameworks and avoid unresolved symbols 
+and flat namespace problems.  The frameworks produce plugins that will
+work on X-Plane 8, 9, and 10 depending on the plugin CPU architecture,
+minimum system SDK, and XPLM API revision number.
+
+X-Plane SDK Release 2.1.1 RC1 10/29/12
+
+The 2.1.1 update to the SDK provides 64-bit build materials.
+
+X-Plane SDK Release 2.1.0 RC1 3/31/12
+
+This is the first release of the version 2.1 X-Plane SDK.  This version of the 
+SDK exposes new APIs.
+
+This API also replaces all references to "long" with int or intptr_t,
+depending on whether the integer needs to be wide enough to hold coerced
+pointers.  Most of the time, int is used; the notable exception is the widgets
+library where params and properties can contain pointers to user data.
+
+This change is not an ABI change - compiled plugins will work unmodified.
+However for some compilers, you may need to replace long with int or intptr_t
+in your code.
+
+X-Plane SDK Release 2.0.1 RC1 7/21/10
+
+This release adds symbol visibility macros for GCC 4 on Linux and corrects a few
+function documentation comments.
+
+X-Plane SDK Release 2.0 RC1 7/11/08
+
+This release includes a corrected XPLM.lib for windows with exports for some of
+the new 2.0 APIs.
+
+X-Plane SDK Release 2.0 Beta 2 4/23/08
+
+This release includes new APIs for reading and writing data files and drawing 
+hooks for the local map screen, as well as some minor tweaks:
+
+- Sim version is 2.0 in the headers.
+- unload plane msg marked as 2.0 only.
+- New enumerations for additional languages.
+- Function level docs improved.
+
+X-Plane SDK Release 2.0 Beta 1 1/19/08
+
+This is the first release of the version 2.0 X-Plane SDK.  CFM support has
+been removed, and the license has been simplified, reflecting that it only has
+to cover the SDK include/import lib files and not the sample code or examples.
+
+X-Plane SDK Release 1.0.2 1/5/05
+
+The headers of the SDK are modified to support Kylix.  No changes for Mac, 
+Windows, or C users.  Headers now have SDK version numbers.
+
+X-Plane SDK Release 1.0.1 12/29/04
+
+The headers of this SDK are modified to support Linux complication.  No changes
+for Mac and Windows users.
+
+X-Plane SDK Release Candidate 1
+
+Only one slight change in the enums: the enum xpProperty_SubWindowHasCloseBoxes
+in XPStandardWidgets.h has been changed to xpProperty_MainWindowHasCloseBoxes.  
+Its value has not been changed, so you will need to search-and-replace your code
+when using this version of the SDK, but already-compiled plugins will experience 
+no different operation.
+
+The documentation has been revised for all headers to revise changes made to the 
+SDK over the course of beta.
+
+X-Plane SDK Beta 5
+
+This version of the SDK features a number of enumeration changes to reflect the
+X-Plane interface more correctly.  This became crucial when X-Plane 7's new user 
+interface was released.  With X-Plane in release candidates hopefully beta 5 of 
+the SDK could be the last one.  Please see:
+
+www.xsquawkbox.net/xpsdk/newui.html
+
+For a comprehensive description of all the enumeration changes.  For most 
+plugins (no developers reported using the deprecated enumerations), a simple 
+search and replace should suffice.  Plugins compiled against the beta 4 SDK that
+do not use now-unsupported graphics will continue to work correctly.
+
+X-Plane SDK Beta 4
+
+This release corrects two problems with the Pascal headers: function pointer 
+types are now declared cdecl (since this is how the SDK calls them), and the 
+import library for the widget callbacks is now XPWIDGETS.DLL as it should be.
+
+X-Plane SDK Beta 3
+
+This release finally features full documentation and a stable widgets API, as 
+well as a few other minor bug fixes.
+
+Starting with beta 3, the DLLs necessary to run plugins ship with X-Plane 660.  
+The SDK will work with X-Plane 660 RC3 and later.  The XPWidgets DLL now lives 
+in the Resources/plugins folder.
+
+Starting with beta 3, extra plugins, documentation, sample code, and sample 
+projects are now featured directly on the web in the new X-Plane SDK library.  
+They are not included in the SDK zip file; the zip file only contains headers 
+and lib files for the SDK.
+
+X-Plane SDK Beta 2
+
+You must recompile your plugin for the beta 2 plugin SDK!  Plugins compiled 
+against the beta 1 SDK will not work with X-Plane 660 or the new XPLM.DLL.
+
+A huge number of data refs have been added.  Unfortunately the documentation 
+is thin.  Use the data ref tester plugin to view the data refs in real time 
+and find what you need.
+
+The data ref APIs have also changed to allow for arrays of integers as well 
+as floats.  Some sim variables are now arrays that were previously many 
+individual items.
+
+A new drawing phase is available for replacing aircraft graphics.  The 
+texturing APIs in XPLMGraphics have been revised.  The most notable change is 
+that you cannot use the SDK to load your textures.  (This functionality was 
+broken and never worked in beta 1.)  See the x-plane-dev list for sample code 
+on how to load your own bitmaps.
+
+X-Plane can reload plugins on the fly.  Use the Plugin Enabler plugin to reload 
+your plugin.  On the Mac you can throw the old DLL in the trash and put a new 
+one in its place to reload a new version of the plugin.  On the PC, an alert 
+comes up; while this alert is up you can swap your plugins' DLL.  This allows 
+you to recompile your plugin without rebooting the sim.
+
+Delphi Pascal interfaces and sample code are in the SDK.  Thanks to Billy 
+Verreynne for his hard work on this.
+
diff --git a/SDK/license.txt b/SDK/license.txt
new file mode 100644
index 0000000..8b9cbfc
--- /dev/null
+++ b/SDK/license.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2008, Sandy Barbour and Ben Supnik
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do 
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice, 
+      this list of conditions and the following disclaimer.
+    * Neither the names of the authors nor that of X-Plane or Laminar Research
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission from the authors or 
+      Laminar Research, respectively.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/JTACCoords/win_x64/JTACCoords.xpl b/build/JTACCoords/win_x64/JTACCoords.xpl
new file mode 100755
index 0000000..5f4e504
Binary files /dev/null and b/build/JTACCoords/win_x64/JTACCoords.xpl differ
diff --git a/compilererror.txt b/compilererror.txt
new file mode 100644
index 0000000..733a4d9
--- /dev/null
+++ b/compilererror.txt
@@ -0,0 +1,358 @@
+x86_64-w64-mingw32-g++ -std=c++11 -Wall -O2 -fPIC -DXPLM200=1 -DXPLM210=1 -DXPLM300=1 -DXPLM301=1 -DXPLM302=1 -DXPLM400=1 -ISDK/CHeaders/XPLM -ISDK/CHeaders/Widgets -I. -DIBM=1 -DWIN32=1 -D_WIN32=1 -c probe.cpp -o probe.o
+probe.cpp:421:19: error: macro "CreateWindowA" requires 11 arguments, but only 1 given
+  421 | void CreateWindow() {
+      |                   ^
+In file included from /usr/share/mingw-w64/include/windows.h:72,
+                 from SDK/CHeaders/XPLM/XPLMDefs.h:32,
+                 from SDK/CHeaders/XPLM/XPLMScenery.h:18,
+                 from probe.cpp:1:
+/usr/share/mingw-w64/include/winuser.h:2206:9: note: macro "CreateWindowA" defined here
+ 2206 | #define CreateWindowA(lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam) CreateWindowExA((DWORD)0,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam)
+      |         ^~~~~~~~~~~~~
+probe.cpp:445:26: error: macro "CreateWindowA" requires 11 arguments, but only 1 given
+  445 |             CreateWindow();
+      |                          ^
+/usr/share/mingw-w64/include/winuser.h:2206:9: note: macro "CreateWindowA" defined here
+ 2206 | #define CreateWindowA(lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam) CreateWindowExA((DWORD)0,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam)
+      |         ^~~~~~~~~~~~~
+probe.cpp: In function ‘void CalculateTargetInfo(const TargetCoords*, float*, float*, float*)’:
+probe.cpp:57:21: error: ‘M_PI’ was not declared in this scope
+   57 | #define DEG_TO_RAD (M_PI / 180.0)
+      |                     ^~~~
+probe.cpp:301:55: note: in expansion of macro ‘DEG_TO_RAD’
+  301 |     double dLon = (target->longitude - aircraftLon) * DEG_TO_RAD;
+      |                                                       ^~~~~~~~~~
+probe.cpp: In function ‘void DrawWindow(XPLMWindowID, void*)’:
+probe.cpp:374:20: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  374 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                    ^~~
+      |                    |
+      |                    int
+probe.cpp:374:40: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  374 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                   ~~~~~^~~~
+      |                                        |
+      |                                        int
+probe.cpp:374:55: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  374 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                              ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                       |
+      |                                                       int
+probe.cpp:374:72: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  374 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                        ^~~~~~
+      |                                                                        |
+      |                                                                        char*
+probe.cpp:374:19: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  374 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |     ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In file included from probe.cpp:2:
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:377:20: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  377 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                    ^~~
+      |                    |
+      |                    int
+probe.cpp:377:40: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  377 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                   ~~~~~^~~~
+      |                                        |
+      |                                        int
+probe.cpp:377:55: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  377 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                              ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                       |
+      |                                                       int
+probe.cpp:377:72: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  377 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                        ^~~~~~
+      |                                                                        |
+      |                                                                        char*
+probe.cpp:377:19: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  377 |     XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |     ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:384:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  384 |         XPLMDrawString(255, 255, 0, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:384:42: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  384 |         XPLMDrawString(255, 255, 0, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                     ~~~~~^~~~
+      |                                          |
+      |                                          int
+probe.cpp:384:57: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  384 |         XPLMDrawString(255, 255, 0, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                         |
+      |                                                         int
+probe.cpp:384:74: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  384 |         XPLMDrawString(255, 255, 0, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                          ^~~~~~
+      |                                                                          |
+      |                                                                          char*
+probe.cpp:384:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  384 |         XPLMDrawString(255, 255, 0, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:390:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  390 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:390:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  390 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:390:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  390 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:390:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  390 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:390:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  390 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:394:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  394 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:394:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  394 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:394:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  394 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:394:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  394 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:394:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  394 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:398:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  398 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:398:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  398 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:398:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  398 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:398:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  398 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:398:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  398 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:405:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  405 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:405:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  405 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:405:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  405 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:405:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  405 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:405:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  405 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:408:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  408 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:408:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  408 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:408:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  408 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:408:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  408 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:408:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  408 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:411:24: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  411 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                        ^~~
+      |                        |
+      |                        int
+probe.cpp:411:44: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  411 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                       ~~~~~^~~~
+      |                                            |
+      |                                            int
+probe.cpp:411:59: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  411 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                  ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                           |
+      |                                                           int
+probe.cpp:411:76: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  411 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                            ^~~~~~
+      |                                                                            |
+      |                                                                            char*
+probe.cpp:411:23: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  411 |         XPLMDrawString(255, 255, 255, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |         ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+probe.cpp:417:20: error: invalid conversion from ‘int’ to ‘float*’ [-fpermissive]
+  417 |     XPLMDrawString(200, 200, 200, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                    ^~~
+      |                    |
+      |                    int
+probe.cpp:417:40: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
+  417 |     XPLMDrawString(200, 200, 200, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                   ~~~~~^~~~
+      |                                        |
+      |                                        int
+probe.cpp:417:55: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
+  417 |     XPLMDrawString(200, 200, 200, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                              ~~~~~~~~~^~~~~~~~~~~~~~~
+      |                                                       |
+      |                                                       int
+probe.cpp:417:72: error: invalid conversion from ‘char*’ to ‘XPLMFontID’ {aka ‘int’} [-fpermissive]
+  417 |     XPLMDrawString(200, 200, 200, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |                                                                        ^~~~~~
+      |                                                                        |
+      |                                                                        char*
+probe.cpp:417:19: error: too many arguments to function ‘void XPLMDrawString(float*, int, int, const char*, int*, XPLMFontID)’
+  417 |     XPLMDrawString(200, 200, 200, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+      |     ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+SDK/CHeaders/XPLM/XPLMGraphics.h:372:21: note: declared here
+  372 | XPLM_API void       XPLMDrawString(
+      |                     ^~~~~~~~~~~~~~
+In file included from /usr/share/mingw-w64/include/winnt.h:9,
+                 from /usr/share/mingw-w64/include/minwindef.h:163,
+                 from /usr/share/mingw-w64/include/windef.h:9,
+                 from /usr/share/mingw-w64/include/windows.h:69:
+probe.cpp: At global scope:
+probe.cpp:421:6: error: variable or field ‘CreateWindowA’ declared void
+  421 | void CreateWindow() {
+      |      ^~~~~~~~~~~~
+probe.cpp:422:24: error: expected primary-expression before ‘params’
+  422 |     XPLMCreateWindow_t params;
+      |                        ^~~~~~
+probe.cpp:422:24: error: expected ‘}’ before ‘params’
+probe.cpp:421:21: note: to match this ‘{’
+  421 | void CreateWindow() {
+      |                     ^
+probe.cpp:423:5: error: ‘params’ does not name a type
+  423 |     params.structSize = sizeof(params);
+      |     ^~~~~~
+probe.cpp:424:5: error: ‘params’ does not name a type
+  424 |     params.left = 50;
+      |     ^~~~~~
+probe.cpp:425:5: error: ‘params’ does not name a type
+  425 |     params.top = 600;
+      |     ^~~~~~
+probe.cpp:426:5: error: ‘params’ does not name a type
+  426 |     params.right = 400;
+      |     ^~~~~~
+probe.cpp:427:5: error: ‘params’ does not name a type
+  427 |     params.bottom = 400;
+      |     ^~~~~~
+probe.cpp:428:5: error: ‘params’ does not name a type
+  428 |     params.visible = 1;
+      |     ^~~~~~
+probe.cpp:429:5: error: ‘params’ does not name a type
+  429 |     params.drawWindowFunc = DrawWindow;
+      |     ^~~~~~
+probe.cpp:430:5: error: ‘params’ does not name a type
+  430 |     params.handleMouseClickFunc = MouseClickHandler;
+      |     ^~~~~~
+probe.cpp:431:5: error: ‘params’ does not name a type
+  431 |     params.handleKeyFunc = NULL;
+      |     ^~~~~~
+probe.cpp:432:5: error: ‘params’ does not name a type
+  432 |     params.handleCursorFunc = NULL;
+      |     ^~~~~~
+probe.cpp:433:5: error: ‘params’ does not name a type
+  433 |     params.handleMouseWheelFunc = NULL;
+      |     ^~~~~~
+probe.cpp:434:5: error: ‘params’ does not name a type
+  434 |     params.refcon = NULL;
+      |     ^~~~~~
+probe.cpp:435:5: error: ‘params’ does not name a type
+  435 |     params.decorateAsFloatingWindow = xplm_WindowDecorationRoundRectangle;
+      |     ^~~~~~
+probe.cpp:436:5: error: ‘params’ does not name a type
+  436 |     params.layer = xplm_WindowLayerFloatingWindows;
+      |     ^~~~~~
+probe.cpp:437:5: error: ‘params’ does not name a type
+  437 |     params.handleRightClickFunc = NULL;
+      |     ^~~~~~
+probe.cpp:439:5: error: ‘gWindow’ does not name a type; did you mean ‘IOleWindow’?
+  439 |     gWindow = XPLMCreateWindowEx(&params);
+      |     ^~~~~~~
+      |     IOleWindow
+probe.cpp:440:1: error: expected declaration before ‘}’ token
+  440 | }
+      | ^
+probe.cpp: In function ‘void XPluginReceiveMessage(XPLMPluginID, int, void*)’:
+probe.cpp:445:13: error: ‘CreateWindowA’ was not declared in this scope
+  445 |             CreateWindow();
+      |             ^~~~~~~~~~~~
+make: *** [Makefile:51: probe.o] Error 1
diff --git a/probe.cpp b/probe.cpp
new file mode 100644
index 0000000..79d7b20
--- /dev/null
+++ b/probe.cpp
@@ -0,0 +1,456 @@
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "XPLMScenery.h"
+#include "XPLMGraphics.h"
+#include "XPLMDataAccess.h"
+#include "XPLMUtilities.h"
+#include "XPLMPlugin.h"
+#include "XPLMDisplay.h"
+#include "XPLMProcessing.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+// OpenGL includes
+#if IBM
+#include <GL/gl.h>
+#elif APL
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+// Data refs for aircraft position and orientation
+static XPLMDataRef gPlaneLatitude = NULL;
+static XPLMDataRef gPlaneLongitude = NULL;
+static XPLMDataRef gPlaneElevation = NULL;
+static XPLMDataRef gPlaneHeading = NULL;
+static XPLMDataRef gPlanePitch = NULL;
+static XPLMDataRef gPlaneRoll = NULL;
+
+// Data refs for view/camera direction
+static XPLMDataRef gViewHeading = NULL;
+static XPLMDataRef gViewPitch = NULL;
+
+// Mouse tracking
+static XPLMDataRef gMouseX = NULL;
+static XPLMDataRef gMouseY = NULL;
+static XPLMDataRef gScreenWidth = NULL;
+static XPLMDataRef gScreenHeight = NULL;
+
+// Terrain probe handle
+static XPLMProbeRef gTerrainProbe = NULL;
+
+// Window for display
+static XPLMWindowID gWindow = NULL;
+
+// Target coordinates storage
+struct TargetCoords {
+    double latitude;
+    double longitude;
+    double elevation;
+    float localX, localY, localZ;
+    bool valid;
+};
+
+static TargetCoords gLastTarget = {0};
+
+// Convert degrees to radians
+#define DEG_TO_RAD (M_PI / 180.0)
+#define RAD_TO_DEG (180.0 / M_PI)
+
+// Earth radius in meters
+#define EARTH_RADIUS 6378137.0
+
+// Plugin lifecycle
+PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc) {
+    strcpy(outName, "JTAC Coordinate System");
+    strcpy(outSig, "com.example.jtac_coords");
+    strcpy(outDesc, "Laser designation coordinate extraction system");
+    
+    // Get data refs
+    gPlaneLatitude = XPLMFindDataRef("sim/flightmodel/position/latitude");
+    gPlaneLongitude = XPLMFindDataRef("sim/flightmodel/position/longitude");
+    gPlaneElevation = XPLMFindDataRef("sim/flightmodel/position/elevation");
+    gPlaneHeading = XPLMFindDataRef("sim/flightmodel/position/psi");
+    gPlanePitch = XPLMFindDataRef("sim/flightmodel/position/theta");
+    gPlaneRoll = XPLMFindDataRef("sim/flightmodel/position/phi");
+    
+    gViewHeading = XPLMFindDataRef("sim/graphics/view/view_heading");
+    gViewPitch = XPLMFindDataRef("sim/graphics/view/view_pitch");
+    
+    gMouseX = XPLMFindDataRef("sim/graphics/view/click_3d_x");
+    gMouseY = XPLMFindDataRef("sim/graphics/view/click_3d_y");
+    gScreenWidth = XPLMFindDataRef("sim/graphics/view/window_width");
+    gScreenHeight = XPLMFindDataRef("sim/graphics/view/window_height");
+    
+    // Create terrain probe
+    gTerrainProbe = XPLMCreateProbe(xplm_ProbeY);
+    
+    return 1;
+}
+
+PLUGIN_API void XPluginStop(void) {
+    if (gTerrainProbe) {
+        XPLMDestroyProbe(gTerrainProbe);
+    }
+}
+
+PLUGIN_API void XPluginDisable(void) {}
+PLUGIN_API int XPluginEnable(void) { return 1; }
+
+// Matrix multiplication helper functions
+void MultiplyMatrix4x4(const float* a, const float* b, float* result) {
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 4; j++) {
+            result[i * 4 + j] = 0.0f;
+            for (int k = 0; k < 4; k++) {
+                result[i * 4 + j] += a[i * 4 + k] * b[k * 4 + j];
+            }
+        }
+    }
+}
+
+void InvertMatrix4x4(const float* m, float* invOut) {
+    float inv[16], det;
+    int i;
+
+    inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
+    inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
+    inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
+    inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
+    inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
+    inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
+    inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
+    inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
+    inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
+    inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
+    inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
+    inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
+    inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
+    inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
+    inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
+    inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
+
+    det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
+    
+    if (det == 0) return;
+
+    det = 1.0f / det;
+    for (i = 0; i < 16; i++) {
+        invOut[i] = inv[i] * det;
+    }
+}
+
+// Convert screen coordinates to local ray direction using OpenGL matrices
+bool ScreenToLocalRay(int screenX, int screenY, double aircraftLat, double aircraftLon, double aircraftElev,
+                      float* rayStartX, float* rayStartY, float* rayStartZ,
+                      float* rayDirX, float* rayDirY, float* rayDirZ) {
+    
+    // Convert aircraft position to local coordinates for ray start
+    double localX, localY, localZ;
+    XPLMWorldToLocal(aircraftLat, aircraftLon, aircraftElev, &localX, &localY, &localZ);
+    
+    *rayStartX = (float)localX;
+    *rayStartY = (float)localY;
+    *rayStartZ = (float)localZ;
+    
+    // Get OpenGL matrices
+    GLfloat modelMatrix[16];
+    GLfloat projMatrix[16];
+    GLint viewport[4];
+    
+    glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
+    glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
+    glGetIntegerv(GL_VIEWPORT, viewport);
+    
+    // Calculate combined model-view-projection matrix
+    float mvpMatrix[16];
+    MultiplyMatrix4x4(projMatrix, modelMatrix, mvpMatrix);
+    
+    // Invert the MVP matrix
+    float invMvpMatrix[16];
+    InvertMatrix4x4(mvpMatrix, invMvpMatrix);
+    
+    // Convert screen coordinates to normalized device coordinates
+    float ndcX = (2.0f * (screenX - viewport[0])) / viewport[2] - 1.0f;
+    float ndcY = 1.0f - (2.0f * (screenY - viewport[1])) / viewport[3];
+    
+    // Create two points in NDC space (near and far)
+    float nearPoint[4] = {ndcX, ndcY, -1.0f, 1.0f}; // Near plane
+    float farPoint[4] = {ndcX, ndcY, 1.0f, 1.0f};   // Far plane
+    
+    // Transform to OpenGL world space
+    float worldNear[4], worldFar[4];
+    
+    // Transform near point
+    worldNear[0] = invMvpMatrix[0] * nearPoint[0] + invMvpMatrix[4] * nearPoint[1] + 
+                   invMvpMatrix[8] * nearPoint[2] + invMvpMatrix[12] * nearPoint[3];
+    worldNear[1] = invMvpMatrix[1] * nearPoint[0] + invMvpMatrix[5] * nearPoint[1] + 
+                   invMvpMatrix[9] * nearPoint[2] + invMvpMatrix[13] * nearPoint[3];
+    worldNear[2] = invMvpMatrix[2] * nearPoint[0] + invMvpMatrix[6] * nearPoint[1] + 
+                   invMvpMatrix[10] * nearPoint[2] + invMvpMatrix[14] * nearPoint[3];
+    worldNear[3] = invMvpMatrix[3] * nearPoint[0] + invMvpMatrix[7] * nearPoint[1] + 
+                   invMvpMatrix[11] * nearPoint[2] + invMvpMatrix[15] * nearPoint[3];
+    
+    // Transform far point
+    worldFar[0] = invMvpMatrix[0] * farPoint[0] + invMvpMatrix[4] * farPoint[1] + 
+                  invMvpMatrix[8] * farPoint[2] + invMvpMatrix[12] * farPoint[3];
+    worldFar[1] = invMvpMatrix[1] * farPoint[0] + invMvpMatrix[5] * farPoint[1] + 
+                  invMvpMatrix[9] * farPoint[2] + invMvpMatrix[13] * farPoint[3];
+    worldFar[2] = invMvpMatrix[2] * farPoint[0] + invMvpMatrix[6] * farPoint[1] + 
+                  invMvpMatrix[10] * farPoint[2] + invMvpMatrix[14] * farPoint[3];
+    worldFar[3] = invMvpMatrix[3] * farPoint[0] + invMvpMatrix[7] * farPoint[1] + 
+                  invMvpMatrix[11] * farPoint[2] + invMvpMatrix[15] * farPoint[3];
+    
+    // Perspective divide
+    if (worldNear[3] != 0.0f) {
+        worldNear[0] /= worldNear[3];
+        worldNear[1] /= worldNear[3];
+        worldNear[2] /= worldNear[3];
+    }
+    
+    if (worldFar[3] != 0.0f) {
+        worldFar[0] /= worldFar[3];
+        worldFar[1] /= worldFar[3];
+        worldFar[2] /= worldFar[3];
+    }
+    
+    // The OpenGL unprojection gives us OpenGL world coordinates
+    // We need to convert these to X-Plane local coordinates
+    // X-Plane's OpenGL coordinate system is already in local space relative to the world origin
+    
+    // Calculate ray direction in local space
+    *rayDirX = worldFar[0] - worldNear[0];
+    *rayDirY = worldFar[1] - worldNear[1];
+    *rayDirZ = worldFar[2] - worldNear[2];
+    
+    // Normalize direction vector
+    float length = sqrt(*rayDirX * *rayDirX + *rayDirY * *rayDirY + *rayDirZ * *rayDirZ);
+    if (length > 0.0f) {
+        *rayDirX /= length;
+        *rayDirY /= length;
+        *rayDirZ /= length;
+        return true;
+    }
+    
+    return false;
+}
+
+// Perform laser designation at screen coordinates
+bool DesignateLaser(int screenX, int screenY, TargetCoords* target) {
+    // Get aircraft position in world coordinates
+    double aircraftLat = XPLMGetDatad(gPlaneLatitude);
+    double aircraftLon = XPLMGetDatad(gPlaneLongitude);
+    double aircraftElev = XPLMGetDatad(gPlaneElevation);
+    
+    // Get ray start and direction using OpenGL matrices
+    float rayStartX, rayStartY, rayStartZ;
+    float rayDirX, rayDirY, rayDirZ;
+    
+    if (!ScreenToLocalRay(screenX, screenY, aircraftLat, aircraftLon, aircraftElev,
+                         &rayStartX, &rayStartY, &rayStartZ,
+                         &rayDirX, &rayDirY, &rayDirZ)) {
+        return false;
+    }
+    
+    // Perform terrain intersection using ray marching
+    const int maxSteps = 1000;
+    const float stepSize = 10.0f; // 10 meters per step
+    
+    XPLMProbeInfo_t probeInfo;
+    probeInfo.structSize = sizeof(XPLMProbeInfo_t);
+    
+    for (int i = 1; i <= maxSteps; i++) {
+        float testX = rayStartX + rayDirX * stepSize * i;
+        float testY = rayStartY + rayDirY * stepSize * i;
+        float testZ = rayStartZ + rayDirZ * stepSize * i;
+        
+        // Probe terrain at this point
+        XPLMProbeResult result = XPLMProbeTerrainXYZ(gTerrainProbe, testX, testY, testZ, &probeInfo);
+        
+        if (result == xplm_ProbeHitTerrain) {
+            // Found intersection - store target coordinates
+            target->localX = probeInfo.locationX;
+            target->localY = probeInfo.locationY;
+            target->localZ = probeInfo.locationZ;
+            
+            // Convert back to world coordinates
+            XPLMLocalToWorld(probeInfo.locationX, probeInfo.locationY, probeInfo.locationZ,
+                           &target->latitude, &target->longitude, &target->elevation);
+            
+            target->valid = true;
+            return true;
+        }
+        
+        // Check if we've gone too far (beyond reasonable range)
+        if (stepSize * i > 50000.0f) { // 50km max range
+            break;
+        }
+    }
+    
+    target->valid = false;
+    return false;
+}
+
+// Calculate bearing and distance to target
+void CalculateTargetInfo(const TargetCoords* target, float* bearing, float* distance, float* elevation) {
+    double aircraftLat = XPLMGetDatad(gPlaneLatitude);
+    double aircraftLon = XPLMGetDatad(gPlaneLongitude);
+    double aircraftElev = XPLMGetDatad(gPlaneElevation);
+    
+    // Calculate bearing using great circle formula
+    double dLon = (target->longitude - aircraftLon) * DEG_TO_RAD;
+    double lat1 = aircraftLat * DEG_TO_RAD;
+    double lat2 = target->latitude * DEG_TO_RAD;
+    
+    double y = sin(dLon) * cos(lat2);
+    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
+    
+    *bearing = atan2(y, x) * RAD_TO_DEG;
+    if (*bearing < 0) *bearing += 360.0f;
+    
+    // Calculate distance using haversine formula
+    double dLat = (target->latitude - aircraftLat) * DEG_TO_RAD;
+    double a = sin(dLat/2) * sin(dLat/2) + cos(lat1) * cos(lat2) * sin(dLon/2) * sin(dLon/2);
+    double c = 2 * atan2(sqrt(a), sqrt(1-a));
+    *distance = (float)(EARTH_RADIUS * c);
+    
+    // Calculate elevation difference
+    *elevation = (float)(target->elevation - aircraftElev);
+}
+
+// Format coordinates for military grid reference (simplified MGRS)
+void FormatMGRS(double latitude, double longitude, char* output, size_t outputSize) {
+    // This is a simplified MGRS format - full implementation would require UTM conversion
+    int latDeg = (int)latitude;
+    int latMin = (int)((latitude - latDeg) * 60);
+    float latSec = (float)(((latitude - latDeg) * 60 - latMin) * 60);
+    
+    int lonDeg = (int)longitude;
+    int lonMin = (int)((longitude - lonDeg) * 60);
+    float lonSec = (float)(((longitude - lonDeg) * 60 - lonMin) * 60);
+    
+    snprintf(output, outputSize, "%02d°%02d'%05.2f\"N %03d°%02d'%05.2f\"W",
+             abs(latDeg), latMin, latSec, abs(lonDeg), lonMin, lonSec);
+}
+
+// Mouse click handler
+int MouseClickHandler(XPLMWindowID inWindowID, int x, int y, int mouse, void* inRefcon) {
+    if (mouse == xplm_MouseDown) {
+        // Convert window coordinates to screen coordinates
+        int left, top, right, bottom;
+        XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);
+        
+        int screenX = x;
+        int screenY = y;
+        
+        // Perform laser designation
+        if (DesignateLaser(screenX, screenY, &gLastTarget)) {
+            XPLMDebugString("JTAC: Target designated successfully\n");
+        } else {
+            XPLMDebugString("JTAC: No terrain intersection found\n");
+        }
+    }
+    
+    return 1;
+}
+
+// Display window draw function
+void DrawWindow(XPLMWindowID inWindowID, void* inRefcon) {
+    int left, top, right, bottom;
+    XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);
+    
+    // Draw background
+    XPLMDrawTranslucentDarkBox(left, top, right, bottom);
+    
+    char buffer[512];
+    int line = 0;
+    
+    // Display aircraft position
+    double aircraftLat = XPLMGetDatad(gPlaneLatitude);
+    double aircraftLon = XPLMGetDatad(gPlaneLongitude);
+    double aircraftElev = XPLMGetDatad(gPlaneElevation);
+    
+    snprintf(buffer, sizeof(buffer), "JTAC Coordinate System");
+    float white[] = {1.0f, 1.0f, 1.0f};
+    XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+    
+    snprintf(buffer, sizeof(buffer), "Aircraft: %.6f, %.6f, %.0fm", aircraftLat, aircraftLon, aircraftElev);
+    XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+    
+    // Display target information if valid
+    if (gLastTarget.valid) {
+        line++; // Skip a line
+        
+        snprintf(buffer, sizeof(buffer), "TARGET COORDINATES:");
+        float yellow[] = {1.0f, 1.0f, 0.0f};
+        XPLMDrawString(yellow, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        // MGRS format
+        char mgrs[128];
+        FormatMGRS(gLastTarget.latitude, gLastTarget.longitude, mgrs, sizeof(mgrs));
+        snprintf(buffer, sizeof(buffer), "MGRS: %s", mgrs);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        // Decimal degrees
+        snprintf(buffer, sizeof(buffer), "LAT/LON: %.6f, %.6f", gLastTarget.latitude, gLastTarget.longitude);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        // Elevation
+        snprintf(buffer, sizeof(buffer), "ELEVATION: %.0fm MSL", gLastTarget.elevation);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        // Bearing, distance, elevation difference
+        float bearing, distance, elevDiff;
+        CalculateTargetInfo(&gLastTarget, &bearing, &distance, &elevDiff);
+        
+        snprintf(buffer, sizeof(buffer), "BEARING: %.1f°", bearing);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        snprintf(buffer, sizeof(buffer), "DISTANCE: %.0fm", distance);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+        
+        snprintf(buffer, sizeof(buffer), "ELEV DIFF: %+.0fm", elevDiff);
+        XPLMDrawString(white, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+    }
+    
+    // Instructions
+    line++;
+    snprintf(buffer, sizeof(buffer), "Click to designate laser target");
+    float gray[] = {0.78f, 0.78f, 0.78f};
+    XPLMDrawString(gray, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
+}
+
+// Create window
+void CreateJTACWindow() {
+    XPLMCreateWindow_t params;
+    params.structSize = sizeof(params);
+    params.left = 50;
+    params.top = 600;
+    params.right = 400;
+    params.bottom = 400;
+    params.visible = 1;
+    params.drawWindowFunc = DrawWindow;
+    params.handleMouseClickFunc = MouseClickHandler;
+    params.handleKeyFunc = NULL;
+    params.handleCursorFunc = NULL;
+    params.handleMouseWheelFunc = NULL;
+    params.refcon = NULL;
+    params.decorateAsFloatingWindow = xplm_WindowDecorationRoundRectangle;
+    params.layer = xplm_WindowLayerFloatingWindows;
+    params.handleRightClickFunc = NULL;
+    
+    gWindow = XPLMCreateWindowEx(&params);
+}
+
+PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void* inParam) {
+    if (inMsg == XPLM_MSG_PLANE_LOADED) {
+        if (!gWindow) {
+            CreateJTACWindow();
+        }
+    }
+}
\ No newline at end of file
diff --git a/probe.o b/probe.o
new file mode 100644
index 0000000..898d873
Binary files /dev/null and b/probe.o differ