Skip to content

GremlinEx Overview

GremlinEx or GEX is a universal controller integrator: it allows you to take input from multiple hardware devices from different manufacturers connected to a local machine, or a remote machine, such as joysticks and HID controllers, OSC (Open Source Control), MIDI, Keyboard and mouse inputs and map them to virtual outputs like VJOY, or keyboard or mouse output, and send that to a game or another process.

GremlinEx is oriented towards simpits and hardware vendor integration, without the need to run individual vendor's software.

The integration piece comes from the ability to combine inputs together into a logical output via a set of filters and transformations, and output this to applications running on the same system.

The project's home is on GitHub from where you can download the latest releases and view patch notes.

The project has a dedicated Discord server where you can lookup solutions to typical mapping questions, how-to, ask questions and report any issues.

Key Features: What can GremlinEx do?

This is a summary of some of the feature set in GremlinEx.

Mapping and transforms

GremlinEx (GEX) takes input such physical (hardware) USB connected joysticks, gamepads, keyboard, mouse, and other specialized input devices like state and OSC network messages, and lets you apply a mapping, also known as a transform, to each input. GEX also understands network inputs that come from other devices on the network via the OSC protocol. GEX supports mapping of buttons, axes, sliders, hats, or more complex inputs such as latched keystrokes (one or more keypress combination), and other input such as MIDI or OSC input (described below). GEX can also remote control other GEX clients on the network, including output of axis, button, keyboard and mouse, as well as two-way controls of hardware panels and glass surfaces via the OSC protocol.

The mapping process can have logic applied to it, such as conditions, so that the mapping can be conditional on a specific context being true. This can be "is this button also pressed", "is this axis value in this range", "are these keys also pressed", "is this state off", all in various combinations. Conditions work across all inputs so one input can be used to manage the mapping of another device.

Axis (linear) input can be curved and calibrated. In fact, multiple curves can be applied, and the curves can be conditional as well. For example, you can invert an axis but only if a condition is true, and when the condition is false, the axis will not be inverted.

GremlinEx handles multiple inputs and outputs concurrently. Routing can change mappings based on conditions, modes and states, and this can be changed dynamically on the fly.

As of M76T68, GEX supports using vJoy as an input and output device simultaneously. This enables scenarios where an input in GremlinEx triggers map to a vJoy device, and when that vJoy device changes, it triggers an input back into GremlinEx to trigger more actions. This can create loops, so care should be excercised to not build a loop regardless of the sequence of events. GremlinEx does not check for loops as they are too expensive performance wise to detect and guard against at runtime.

Agreggation of multiple devices

GremlinEx is designed to simplify mapping for a game or application so that the application has much fewer devices to map. The first major benefit is to reduce the number of input devices, as many titles only "see" a few joysticks, and if you have a simpit, you could have left, right, center controllers all connected at the same time, and you may use some of them, or all of them, to map to the same input. This can be very difficult to do in some games.

GremlinEx is vendor agnostic so any mapping software that is proprietary to a particular manufacturer does not need to be used in most cases. GremlinEx will use the raw device capabilities as seen by Windows, so as long as the device shows in Windows without software as a game controller, GremlinEx can create mappings for it.

GremlinEx can combine inputs from multiple types of devices: GremlinEx lets you merge data from different devices (such as axes on two or more controllers), or use controller button and axis values as conditions to decide if other output should go through or not.

Dynamic routing

Because GremlinEx has conditions and modes and states, you can "route" the input to different outputs, as well as modify the output in a dynamic way. You can take a single input and map it to different outputs depending on what you need. So a toe brake on a rudder can become an accelerator or brake pedal for a vehicle on the ground, or an up/down strafe if you are in a spaceship, or plain toe brakes if you are in an airplane with differential left and right brakes. You can have a button that is normally your primary trigger button control different weapon groups depending on the mode GremlinEx is in. An axis can inverted dynamically, or different response curves applied to control, for example sensitivity.

VJoy output

The main purpose of GremlinEx is to map inputs from various devices to VJoy virtual joystick devices. The idea is while the actual joystick hardware connected to the machine is hidden from an application or game via HidHide, the application or game can then map its inputs to the virtual VJoy devices. This allows much simpler mapping in a game when multiple hardware devices are available, as well as very complex mapping scenarios using conditions, modes, combination of inputs, tracking of state applied to the logic controlling the VJoy devices. This feature, when combined with mouse and keyboard management done by GremlinEx allows for a highly customized experience with application and game control.

VJoy as input

GremlinEx supports concurrently VJoy as an output device, as well as VJoy as an input device in the same profile. When a VJoy device is configured as an input, it will add a new VJoy device to the list of input devices that can be mapped to in GremlinEx. When the VJoy button, hat or axis is set, either by another GremlinEx mapping, or a third party application, the input will trigger and GremlinEx will generate output based on the mappings for that input.

By design a mapping that triggers a VJoy output will also trigger that VJoy's input, if mapped and enabled, from the same profile. This allows VJoy to be used as a bank of axes, hats and buttons for multiple parts of a profile to interact with. A common scenario is to setup extra VJoy devices to increase the number of buttons, hats and axes GremlinEx can use to keep track of states without having to use custom plugins, or the GremlinEx state machine.

warning It is generally discouraged to use the same VJOY device both as input and output in the same profile due to API limitations that can lead to race conditions, execution loops and deadlocks where VJOY devices could become "locked". This is because the VJOY software is designed for it to be used per process as either input or output, not both (while possible as we work around this in GEX). VJOY as input is meant to be used as a way to capture VJOY input data set from a different process (application). It is supported in GEX, but has caveats that need to be considered when designing the profile to avoid these issues.

warning VJOY input devices tend to create a significant number of inputs that GEX needs to track - up to 140 inputs per VJOY device used as input. This can degrade user interface (UI) performance and increase the memory footprint at design time because of the need to visualize and track all these inputs. Use the input filtering option available as of m76T115 to reduce the number of inputs visible in VJOY devices to keep the input count to a reasonable level. The impact level is based on hardware capabilities, and the total number of inputs managed by GEX. It is usually not an issue until you start getting into 400 to 500 inputs GEX has to track at the same time at edit time. This does not impact runtime performance at all. If you start noticing edit time performance degradation, it is likely due to the number of inputs and filtering should be used to keep that to a reasonable level.

VJoy manual control

GremlinEx's Input Viewer, as of m76T95, can be used to manually set buttons, hats and axes on any VJoy device interactively via the Input Viewer. This can be helpful to assist with profile design and testing.

In-game mapper augmentation

GremlinEx can achieve very complex mappings that are not supported by a game. It can take complicated inputs (such as from multiple controllers) and map it to something the game does support, and the game does not need to be aware of these inputs, as it will not see them. The game will only see a supported command.

For example, you can combine inputs such as a keyboard key in combination with a joystick button and map that to a unique function in the game, even if the buit-in game mapper does not support these kinds of cross-hardware combinations.

Easy mapping to game defaults

Certain titles have less than ideal mappings, for example, not supporting DirectInput joysticks but having support for a console game controller. GremlinEx can bridge this gap by producing output the game expects, even if the game doesn't support specific inputs that GremlinEx supports.

It is generally recommended to use GremlinEx to map to default settings in a game, which avoids having to change mappings in the game itself. This can greatly simplify game mapping for simulators in particular.

Input and output from/to glass surface panels (touchscreens)

GremlinEx map input from/to glass surfaces (touch screens) and hardware panels like Streamdeck using the OSC protocol using open source software. Using OSC open source software like Open Stage Control, you can design custom glass surface input screens and map them over the network to GremlinEx. GremlinEx supports both message triggers, and axis including multi-axis data inboud from a glass surface, such as a slider or an XY pad.

Networked devices support

GremlinEx has a built-in capabilityu to use controllers attached to one computer to control another and deliver the output to a game over the local network.

Direct support for Microsoft Flight Simulator

GremlinEx has built-in support to directly control Microsoft Flight Simulator without using the internal MSFS mapper. It uses the SimConnect interface to do this, and a custom WASM module to access internal variables not supported via SimConnect (as of this writing).

Profiles

In GremlinEx, a set of device mappings is saved as a profile. The profile contains all the configuration and mapping information from an input to an output. Profiles are usually associated with a particular target application. GremlinEx has a mapping feature that lets you attach a profile to one or more Windows processes. GremlinEx can switch to the associated profile when the process becomes active automatically.

Profiles are saved as XML files. Because they contain specific hardware information that is unique to the machine, profiles cannot usually be shared from one machine to the other. GremlinEx does include some simple mapping when you attempt to load data for a device it cannot find. In this case the profile will load and show devices it cannot find as disconnected. Their mappings can be copied to devices that do exist.

Important: device IDs can often change in Windows when new firmware is applied to a device, or the device is connected to a different port. The same device connected to different machines will typically have a different ID specific to that machine as well.

For this reason it is highly recommended to minimize connecting/disconnecting hardware devices, to avoid potential ID changes as these can be quite time consuming to resolve.

Note: GremlinEx uses the ID of the hardware, not the index of order of appearance so the order the devices appear in Windows is not relevant to GremlinEx's operation.

Joystick and game controller integration

GremlinEx accepts inputs from any number of HID game devices and maps this input, apply a number of transformations and filters, and creates output virtual joystick (Vjoy) device, a virtual gamepad controller (via Vigem), keyboard and mouse output, OSC network messages and others. GremlinEx supports input from Arduino and Rasberry Pi when those devices are in HID "game controller" mode.

GremlinEx supports HID devices that report as game devices, and the supported inputs for each includes linear input (axis), momentary input (button) and four or eight way hats. HID devices under Windows are limited to 8 axes, 128 buttons and four hats per device.

GremlinEx also has a loopback mode where VJOY devices can be used as inputs. In this mode, GremlinEx will not be able to map outputs to the same input as that would create a loop. This feature is intended for other software that also uses VJOY to provide input to GremlinEx.

HIDHide support

GremlinEx is designed to function with HIDHide. HID Hide enables "hiding" of HID inputs that could conflict in a game with the mapping done by GremlinEx when detecting inputs. Many games also only support a finite number of HID devices, and many cannot handle more than three.

HIDHide solves both these problems: the idea is to "hide" the raw hardware inputs used by GremlinEx from the game so they are only visible to GremlinEx. This way, the game only sees the GremlinEx output devices (VJOY and VIGEM) when doing the in-game mapping, and does not see the devices actually connected to the machine. There are thus no conflicts and no confusion with the in-game mapper as to "which device am I reading from".

It is essential to have the GremlinEx executable white listed in HIDHide so it sees the raw hardware devices.

Axis curves

GremlinEx can apply linear, cubic and bezier curves to an axis (linear) input to modify the input response, the output response, and both concurrently. Such curves are usually called response curves or sensitivity curves. Multiple curves can be applied to the same input, for example, a curve on the input itself, and a curve on the outputs. Curves applied to outputs are only applied to a particular mapping. Curves can be manipulated, and GremlinEx supports presets, both built-in and custom user.

It generally is not appropriate to apply two response curves on the mapping side as that can lead to undesirable output values, so while it's possible, ensure the applied curves do not inadvertently produce undesirable data.

While curves can be applied as a standalone mapping, it is recommended to apply curves directly to the vjoy remap action. One reason: this curve is applied to the merged axes. Execution at runtime is also faster as it avoids a step.

Profile modes, states and condition let you control how and when curves are applied, so you can, for example, have two or three sensitivity settings for an axis output based on the state of input buttons on a hardware panel, or you can toggle them by pressing a button.

Axis calibration

GremlinEx can apply calibrations to noisy joystick inputs to dampen the input received. The calibration can automatically detect the range of inputs and normalize it to min/max values, and adjust the center position as well. Calibrations apply to the device, and thus to all profiles.

Rare: If you need to apply different calibrations to each device on a per profile basis, please use the response curve ex action.

Axis gating and splitting

GremlinEx supports several axis splitting tools, including the advanced Gated Axis that introduces the notion of gates (fixed points on an axis) and the ranges between them. Gates and ranges have their own trigger points. Gated axis is aware of when a gate is crossed, the direction the crossing happened, and if the current position is entering or exiting a range, outside a range, or within a range.

GremlinEx can trigger separate mappings (actions) when the input axis crosses a gate or is within a range.

Because each gate or range has its own separate triggers, it allows for very detailed and customized control of mappings at specific points, or within ranges of the axis or slider.

Gated Axis Examples

  • to implement gates on an axis like on aircraft throttles, such as the F16, A10, Airbus throttle or a turboprop aircraft for flight simulation and helicopter collectives, and thrust reverse mapping.
  • to trigger different output based on the direction of travel when the input crosses a particular point.
  • to implement multiple response curves on the same axis by section.
  • to split an axis into several non linear ranges, each with its own output curve, scale, direction, including no output/deadzones.
  • to trigger outputs based on the direction of travel on the input, so a trigger passing through a point going up can be different from a trigger of the same point going down.
  • to scale output within a range
  • to setup deadzones or fixed value zones within an axis (no output or fixed output while in range)
  • to support gated hardware or physical detents on input hardware that does not trigger inputs at these locations
  • to implement virtual hardware detents if the hardware does not support physical detents

Axis merging

GremlinEx's vjoy mapper can merge multiple input axes (two or more) from the same or different devices. Each merge can apply a specific calculation such as min, max, average and sum operations to the merged data. Scaling of one axis with another is also supported.

A use-case for this feature is the need to combine two inputs into a single output, such as brake pedal toe-brakes to a single linear axis (used in Star Citizen staffe for example).

Another use case is to scale one axis with another.

Mergine of axes is helpful in many output scenarios, and the merging can also be controlled on the fly using profile modes, conditions and profile states to, at runtime, control how merging occurs.

Integrates with Elgato (R) Streamdeck, LoupeDeck and any support panels by BitFocus Companion

GremlinEx integrates with any control surface supported by BitFocus Companion via the OSC protocol. This is a two way communication so GremlinEx can accept OSC messages triggered by Bitfocus Companion, and send messages back to BitFocus Companion to update the panels. With this integration, it is possible for GrmelinEx to accept input, and send data back to hardware panels connected locally and on the network.

Examples of this include:

  • call up pages on Streamdeck or Loupedeck on profile load or mode activation
  • map rotary encoders from Streamdek or Loupedeck
  • map buttons and sliders to GremlinEx as input
  • modify panel buttons or messages from GremlinEx
  • use Bitfocus Companion and GremlinEx only (no need for custom software from each vendor specific to their panel and worry about protocols or plugins).

Click here to see the extensive list of supported hardware devices through Bitfocus Companion.

Supports glass surface input from touch screens, tablets and phones

GremlinEx uses the OSC protocol to get input and send data back to glass surfaces via applications such as Open Stage Control (open source), Hexler Touch/OSC (payware) and OSC/Pilot (payware). These applications let you design any control surface on a touch panel, including buttons, knobs, faders, XY pads.

The recommended application for Windows touch screens is Open Stage Control: it is open source and it supports javascript scripting, CSS based graphics and animations including strips, and custom CSS based widgets. Open Stage Control is currently supported on some flavors of Linux as well.

The recommended application for iOS and Android is Touch/OSC, althoug as of this writing, Touch/OSC is incapable of using images but has good scripting via LUA. OSC/Pilot supports graphics and works on iOS as well. OSC/Pilot as of this writing does not support scripting.

This enables any networked touch screen to be used with GremlinEx as a two-way control surface.

Note: Windows is currently not able to support input from a touch screen without changing the focus to the touch screen window away from the game, which can cause some challenges with process focus and window pops and input capture, even on multiple monitors. To use a touch screen, it's recommended to run the touch screen from a separate network device. Because OSC is a network protocol, GremlinEx can easily communicate with these tools on different devices on the network.

Supports MIDI inputs

GremlinEx can accept input from older MIDI controllers. These controllers like the Korg Mini include buttons and faders that can be used to map to a game. Many MIDI control surfaces, while using an older protocol, can still be effective in a simpit due to the number of knobs, faders and buttons typically available on a MIDI controller. It's also possible to network MIDI via RTP-MIDI.

To use local MIDI devices, a MIDI loopback tool will typically be needed to make the necessary ports available.

State machine

GremlinEx implements a state machine. A state is a binary entity that has either an on/pressed state, or an off/released state. A state can be seen as a virtual button, or a boolean (on/off) variable inside a profile.

States can be set or cleared via any GremlinEx input using the Map to State action.

The value of a state can also be defined using other states using boolean expressions. In this mode, a state gets its value from a computation of the dependent states in the expression. This value is updated whenevever one of the states in the expression changes values.

States look like input buttons to containers and actions, so any mapping that can be attached to a button can be attached to a state as well.

States can also be used as conditions.

States are mode agnostic - so they exist all the time in a profile, and can be accessed by any mode, or set by any mode.

This feature allows simple, yet interesting grammar based control schemes, such as conditions and compound mappings. States generally simplify complex mapping scenarios.

States can be set from any input via the "map to state" action or from a macro.

States auto-update if the state is an expression and a dependent state changes.

States trigger both a press and release event, so to actions look like any joystick button and no different from pressing and releasing a physical button.

Because there is no limit to the number of states a profile can have, states can be also viewed as virtual button pads.

Examples of state usage

  • A state can be set by multiple inputs, enabling shared used of mappings between devices. This avoids having a copy of the same mapping for differentt inputs, and reduces the maintenance load if the mapping needs to change.
  • States can be used as a condition that itself is based on multiple other states using the expression capability.
  • Setup a simple state machine grammar implementation
  • States can often replace modes, or be used as sub-modes within a mode.
  • States replace the need to use VJOY as input which is far more performing and flexible than using VJOY as both output and input into a profile to add virtual buttons.

Modes

Modes represent a set of mappings in a profile. A profile has at least one mode, called the default mode, and appropriately named "Default". Modes contain a set of mappings across all devices, except for states, as states are profile wide and work in any mode. If two modes are created, say A and B, mappings in B can be different from A, essentially having a duplicate set of modes. A practical example of this is for a Flight Simulator, you can have a mode per aircraft type, each with different input mappings suitable for that aircraft, so for example, using a side stick for an Airbus or a fighter jet, and a yoke for a Boeing or general aviation aicraft. Or you can have a mode for driving, a mode for first person, and a mode for flying.

Modes can be toggled from inputs, and modes can also be cycled temporarily or in sequence in round-robin fashion.

Modes are hiarchical as well. A mode can have multiple child modes and each mode can have a parent mode. Because each mode has its own set of mappings, the way modes work is that if a child mode has no mappings defined, it inherits the mappings of the parent mode. If a mode does define a mapping, and that is also defined in the parent, the child mapping overrides the parent.

When a profile starts, GremlinEx can trigger a mode change to the startup mode defined in the profile configuration as the startup profile.

Modes also have a pair of triggers associated with them, so a mode can trigger mappings on mode entry, or mode exit. This can be used for example to reset values. These are set in the Mode/Profile tab.

A profile must have one mode defined at all times.

Remote control and KVM support

GremlinEx can control another GremlinEx instance running on the local network. This is useful if you have HID devices on one machine, but need to send that output to another machine on the network. GremlinEx sends the same output to network clients, and buttons can be mapped to enable or disable the feature on the fly.

This particular feature is used to use inputs from one machine to control outputs on another on the fly. This was created specifically to support simpits with multiple computers accepting inputs either for performance reasons, hardware needs, or for convenience. This is a good use of older hardware as well.

A special action, called KVM, lets you take over a specific client and send all local keyboard and mouse to that client without any mapping needed.

Conditions

Conditions can be applied to filter output based on state and input button/axis values. Conditions can be based on specific input ranges or pressed/released state, and can also be based on a state value. Conditions must be met for a trigger to execute a mapping.

Conditions can be applied to a container, or a single action. Conditions are cummulative, meaning that each mapping can have one or more conditions applied.

Support of complex latching of keyboard triggers

GremlinEx can trigger on multiple key combinations, including unusual ones. It is possible to setup a trigger that requires five keys to be pressed at the same time. Any key and mouse input can be used in the latching trigger.

Support of atypical keys

GremlinEx supports input/output of atypical keys such as media controls (for volume and playback control) and F13 to F24. GremlinEx also treats mouse output as a key, which is helpful for some scenarios. The keyboard mapper can output any mouse button and wheel output (mouse motion is also supported via the mouse mapper if mouse motion is needed).

Targeting of specific processes

GremlinEx also has for each output the notion of a press (make) and release (break) and works at very low levels in Windows, and is able to target a specific process, including background processes.

Pulse function

Most momentary outputs like joystick buttons, key and mouse buttons, and SimConnect have a pulse mechanism. The pulse allows GremlinEx to send repeated outputs while the input is triggered, and stop when the input is released. Some outputs have a pulse duration (how long the pulse is - or the time between a press/release cycle triggered by the pulse), and a pulse interval, which is the time between pulses. Some outputs can only be momentary (example, SimConnect), and thus only have a pulse interval value to set.

Macros

GremlinEx supports macros in a couple of ways. The first is the macro mapper, which allows for delays, keyboard, mouse and joystick output to occur in sequence whenever an input is triggered. The other is the sequential container which allows for actions that are not directly supported by the macro.

In both cases, the order of output is always top to bottom, so the execution order is predictable.

Audio playback support for .WAV and .MP3 with fader/speed controls

GremlinEx can playback audio files in the .WAV and .MP3 format (.WAV recommended for performance). The playback action can play random sounds from a specific folder, and it can play multiple sounds concurrently on the same or multiple audio devices. The action can also fade the sound in or out, and adjust the playback rate in a pitch controlled manner (the pitch will not change based on the playback speed).

This action can be use to output audio cues for specific actions.

Text to speech

GremlinEx supports TTS (text to speech) using the internal Windows TTS API and can leverage multiple languages based on installed language packs. This said, with the /available AI tools online, it is recommended that the TTS action be replaced by the playback of .WAV files instead which is more performant at runtime than the older TTS Windows API with often a significant quality improvement in audio as well.

Random execution

GremlinEx can, via the sequence container, output randomized actions, either in a loop or not, with varied timings called "wiggle" mode. This enables randomized output to be selected from a list of actions to execute, in round robin fashion or not.

Concurrent output and input

GremlinEx can output to multiple devices and clients at the same time, and accept concurrent input as well due to its multi-threaded approach.

Profile start and stop triggers

GremlinEx has the ability to execute containers and actions at profile start, and profile stop. This enables you to configure outputs in a known, specific way, whenever a profile is started, and return to a known setup on profile stop.

Mode start and stop triggers

GremlinEx can execute containers and actions when a mode is entered, or a mode is exited.

Synchronization at profile start

Many actions have the optional ability to read the current state of the input (for example the position of an axis, a switch state) on profile start, and to synchronize the output to that input. This is helpful to ensure that hardware switch positions and axis output (such as a throttle) are reflected by the output to match the input.

Available Containers

GremlinEx has a rich set of mapping actions aimed at simulation and game output. These actions are defined inside containers. Containers types have different functionality to determine how these actions are executed. Containers also have conditions applied to them optionally, either at the entire container level, or the individual actions contained within containers. It should be noted that some containers may handle conditions differently based on what they do.

The most basic container is called "basic" and is the default container for any action added to an input.

The table below shows the list of delivered containers:

Container Input Requirements Description
Basic Any Simple container that defines actions to execute. This is the most common container. When an action is added, a basic container is created to contain it.
Press/Release Button A container that executes two sets of actions, one for when the input is pressed, the other for when the input is released.
Chain Button A container that executes actions as chained steps. Each trigger of the container advanced the step. When the last step is executed, it loops back to the first step.
Double Tap Button A container that runs its actions on input double click.
Hat Buttons Hat A container that maps hat input to buttons (nine possible actions, one for each hat position, and the hat center).
Range Axis A container that triggers when the input is in a given range. For more sophisticated mapping of an axis, use the gated axis action instead.
Repeater Button A container that repeats (pulses) the contained actions. The container has an initial optional delay before auto-repeating if needed. This container mimics the firmware keyboard autorepeat function. The input is initially pressed, and if still pressed after the initial delay, continues repeating while the input is pressed. The initial delay can be set to 0 to immediately start repeating.
Sequence Button A container that runs steps like a macro. Unlike a macro, steps are full actions which adds more functionality, and the container can randomize in "wiggle" mode the step order, the time between steps, and the duration of each step (duration defined as the time between a "press" and a "release" for each step), and can execute a range of steps picked at random. This container is a superset of the macro action.
Smart Toggle Button If the input is held down the action will perform as a typical remap action would, i.e. staying active as long as the input is pressed. However, when a short button press is detected, specified by the Toggle time then the first such press toggles the down state, i.e. holding the action down, and the second short press releases the action again.
Switch Button This container triggers defined actions based on the input value. It can trigger on press, release or whenever the input state changes.
Tempo Button This container performs actions based on short tor long press. Legacy container preserved for legacy profiles.
TempoEx Button This container is an enhanced version of the legacy Tempo container and adds the ability to trigger on double click, along with various other new options not in Tempo.
Tick Axis This container triggers actions at defined ticks on the input axis. For more sophisticated mapping of an axis, use the gated axis action instead.
Trigger Button This container triggers actions in the future. When the delay lapses, the container evaluates an optional set of conditions to determine if the actions should run or not. The conditions evaluated are different from the regular container conditions. Trigger conditions are tested at the time the delayed actions run, whereas the regular conditions are evaluated to determine if the container should trigger in the first place.

Available Actions

GEX has a number of custom actions that perform the actual mapping of inputs to outputs. Actions are contained by containers.

Action Input Requirements Description
Control Button This action can set various runtime options for GEX and are aimed at changing profile behavior at runtime.
Cycle Modes Button This action steps through the defined list of profile modes. Every trigger advances the step. When the last step is selected, it loops back to the first step.
Description Any This action does nothing outside of adding a description to a container or action.
Gated Axis Axis This action defines gates (positions on an axis) and ranges (space between two gates) and lets you map other actions based on the current axis position. Gates can trigger a different set of actions based on how the gate is crossed: any direction, crossing down, or crossing up. Gates support button actions. Ranges trigger different action sets based on entry, exit, any change while the input is in-range, or any change if the output is outside the range. Ranges can also re-scale the value or invert it, or send a fixed value, or send no value. Ranges support axis actions. Gated Axis is designed to split up an axis and is used heavily in flight simulation and throttle mapping or whenever specific actions need to run at specific intervals or positions of travel for a given input axis.
Macro Button This action defines stepped macros including joystick, keyboard, mouse and state. The big brother version of macros is the Sequence container that has even more options for macro-like functionality.
Map to Gamepad Any This action maps to game controller output via VIGEM.
Map to Keyboard Button This action is the legacy keyboard mapper. Its purpose is to output a key.
Map to Keyboard/Mouse Ex Button This action maps to one or more keys, including extended keys and media keys, and mouse buttons and mouse wheel. Supports repeat, pulse, press, release, toggle and other modes.
Map to Mouse Button or Axis This action maps to mouse output, including mouse axes or mous ebutton. This is a legacy action to be compatible with older profiles.
Map to MouseEx Button or Axis This action maps to mouse output, including mouse axes or mous ebutton. This is the new version although for mouse button output, consider using Map to Keyboard/Mouse Ex.
Map to Octavi IFR1 Button This action is specific to controlling the Octavi IFR1 device.
Map to OSC Button This action sends OSC messages to the network. This allows GEX to update glass surfaces and panels via OSC.
Map tp OSC Ex Button This action sends OSC messages to the network. This allows GEX to update glass surfaces and panels via OSC. More advanced version.
Map to Simconnect Button or Axis This action sends commands to Microsoft Flight Simulator 2020 or 2024. Includes support for calculator expressions to control add-ons via the GEX WASM module. This allows GEX to control axes and functions in the simulator without having to use the internal Flight Simulator mapper. Requires MSFS to be running on the same machine as GEX.
Map to State Button This action manages GremlinEx's state machine. It can be used to set or clear states.
Map to Trigger Button This action issues a "fake input" to the profile for any supported device. This action mimics the input being triggered on the real device.
Map to Vjoy (Vjoy Remap) Any This is the updated action to map to VJOY devices. Supports various modes, including axis merging and output curves for axes.
Noop Any This is a no-op (do nothing) action. This is used when you use a container that requires an action, but you do not want anything to happen.
Pause Any This pauses the profile execution. See Resume.
Play Sound Button This action plays an audio file (.wav or .mp3). Wav is recommended. This action can also be used to generate AI voices from text if KTTS is installed and GremlinEx runs as a script (not a package). Once the audio files are generated, KTTS is not needed and the regular small form factor packaged version of GEX can be used.
Previouse Mode Button Changes to the prior profile mode.
Remap Any This is the legacy VJOY mapper and is there to maintain compatibility with legacy profiles. Use Map to Vjoy (Vjoy Remap) instead.
Response Curve Axis This is a legacy curve adjuster that applies the curve to the other actions. This is legacy action to maintain compatibility with legacy profiles and the functionality is completely integrated with Map to Vjoy. Use Map to Vjoy (Vjoy remap) instead.
Response Curve Ex Axis More advanced version of Response curve, from an early version of GEX. Use Map to Vjoy (Vjoy remap) instead.
Resume Button This resumes execution of a profile suspended with the Pause action.
Run Process Button This action runs an external process (.exe) from the profile.
Split Axis Axis Legacy action to maintain compatibility with legacy profiles. Please use Gated Axis instead.
Switch Mode Button This action changes the profile mode.
System Button This action is similar to Control.
Temporary Mode Switch Button This action will cause a mode switch when the input is pressed, and change it back to the current mode when released.
Text to Speech Button This action will generate an audio message using the legacy WIndows TTS API in real time. Play Sound is recommended and this legacy API is known to conflict with the audio layer and voice quality and choices are limited. It is also much slower and uses more resources than playing a .wav file.
Toggle Pause Button This action toggles a profile execution. See Pause and Resume.

Custom plugins (advanced)

GremlinEx exposes much of its internal API to custom Python based modules that can be attached to profiles. User plugins are attached to a profile, and are loaded dynamically when the profile starts. User plugins can be used to further provide complete control of mappings and output using the full Python language. Gremlin defines a number of decorators to make programming simpler, however GremlinEx also exposes its event system to plugins, so plugins can respond to events just like internal GremlinEx components can.

Plugins can be used to set LEDs, or do complex logic that would be difficult to do with states and conditions alone.

User-defined mapping plugins and containers can also be created and installed into GremlinEx. These need to meet specific requirements and allow custom expansion of GremlinEx capabilities. Most containers and actions in GremlinEx are implemented using these plugins.

Visualization

As of m76T85, GremlinEx can create a graphical view of a profile leveraging the open source GraphViz library. This creates a PDF or SVG visual graph of the profile (PDF is recommended)

Visualization

Supported environments

GremlinEx supports Windows x64. The resource section covers the recommended versions and software.

Installation

GremlinEx comes as a pre-packaged Python 3.x executable. There is no need to install Python or dependent libraries as all the needed files are included in the package.

Microsoft Flight Simulator SimConnect SDK support

GremlinEx comes with a WASM module for Microsoft Flight Simulator that must be placed in the community folder. This module enables GremlinEx to send calculator expressions to the simulator to control aircraft and systems not available yet via the SimConnect SDK.

GremlinEx was tested with MSFS 2024 including all current beta versions.

VJoy support

GremlinEx was tested with VJOY 2.1.9.1 64bit. There are several releases of VJOY however however 2.1.9.1 is the one tested and verified to function with Windows 11. Please see the resource section.

GremlinEx does not currently support force feedback inputs, nor output via VJOY.

GremlinEx supports up to 8 axes, 128 buttons and four 8-way hats on each VJOY devices.

It is recommended to have no more than three or four output VJOY devices, the primary reason being that many games only understand the first three HID devices.

warningAll defined VJOY devices must have a unique combination of axis, button or hat counts. This is how these devices are differentiated as different devices as they all have the same name as currently defined in the device driver. GremlinEx will throw an error if two VJOY devices have identical numbers of axis, buttons and hats. The suggested method is to remove a button, so the first can be setup with 128 buttons, the second 127, and the third 126, etc... Another popular method is to change the number of hats per device.

General structure of GremlinEx

GremlinEx is written almost entirely in Python 3.1x, with a pair of exceptions: the Python to DirectInput interface is in C++ and the WASM module for Microsoft Flight Simulator is also in C++ as it is a module loaded by MSFS. All are open source on GitHub, and some are either direct forks or inspired by existing open source samples:

All come pre-packaged for convenience of intallation to avoid having to install anything. All requirements however can be compiled from source if needed. Visual Studio is required for the C++ interfaces. The recommended environment for Python is Visual Studio Code.

The general distribution includes a zip file to extract to a folder, recommend to avoid system folders and instead pick a root folder on a drive somewhere on the system.

Profiles and data files

Profiles are stored in XML format in the general user profile folder, called Joystick Gremlin Ex. The location of the user data folder is part of the Windows configuration. This folder is created automatically if it does not exist.

Optionally GrmelinEx can create folders for each version of GremlinEx to avoid in debugging as some patches do change XML profile structures making them incompatible with a prior release. GremlinEx does minimize this by usually ignoring extra data or having suitable defaults for data found to be missing due to an added feature. In general, versioning of the user data folder for GremlinEx is not necessary, so the option is off by default.

GremlinEx also uses this data folder to store its options as a JSON file, as well as calibration data if provided.

Inputs

An input in GremlinEx is either a hardware input (from a connected device like a joystick or throttle for example), a keyboard/mouse input ("when I press these keys or these mouse buttons I want this to happen..."), OSC input to accept inbound OSC messages, MIDI messages for MIDI input messages, and States for mappings that shouldl trigger when a state changes.

There are two types of inputs:

  • linear (such as an axis)
  • momentary (such as a button, including hats)

Mappings

A mapping is a set of containers and actions attached to an input. A mapping includes at least one container, the simplest one called the basic container. The type of containers and actions available depend on the input type. So actions for an axis are different from actions for a button.

Containers contain one or more actions. Many containers are specialized and add functionality to actions, such as chain or sequence, or long/short press functionality. Containers by themselves do not produce any output, but they manage the behavior of the actions they contain.

Some actions, like Gated Axis, also have containers embedded in the action for each trigger condition.

Actions are the actual items that produce output.

Note: it is usually the case that different combinations of containers and actions can produce the same output. There is no method better than the other. The key is to pick a combination that works for you. It is also the case that while many actions are similar (they may even be called the same except for an "ex" for "extended functionality"), that some may be better than others as they offer different output options.

For example, a simple key press can be output using a macro action with three steps (press key, pause, release key), or a single map to keyboard/mouse Ex action in pulse mode.

If you have a mapping questions such as "How do I do this", please ask the question in the binding discussion forum on Discord.

Templates

GremlinEx lets you save mappings to a template file, which only contains the mapping configuration and does not have any input information. Theses are XML files, like profiles, that can be used to store specific setups and re-use them across multipel profiles by loading them from the file into the mapping.

Templates are also a good way to share profile setups with others as mappings don't require any input data. They only require that a mapping for a button is attached to a button type input, and an axis type mapping is attached to an axis input to avoid errors.

Hardware Inputs

GremlinEx listens to local hardware devices using thw Windows DirectInput API which is part of DirectX. This APi sees game controllers attached to the machine that report as game controllers. Of importance here is GremlinEx typically does not use the VJOY interface to read VJOY data, but the DirectInput. There are some exceptions as there are a couple of places where GremlinEx will validate the VJOY data directly via the VJOY API.

GremlinEx listens to keyboard and mouse input via the Windows API.

Custom plugins can read data using the GremlinEx or Python APIs.

HIDHide should be configured to white list the GremlinEx process so GremlinEx can "see" the raw hardware hidden from games.

Hardware Output

GremlinEx sends VJOY (virtual joystick) and VIGEM (virtual game controller) via their respective APIs.

GremlinEx sends keyboard and mouse output via the Windows API.

Custom plugins can send data using the GremlinEx or Python APIs.

Network

OSC traffic

GremlinEx listens to and transmits OSC traffic via UDP ports per the OSC protocol specifications. GremlinEx will decode OSC packets and interprets them based on the data they contain, including a command, and any parameters sent with this command. This supports Bitfocus Companion data, as well as glass surfaces.

It is important that ports are open via the Windows firewall (this should be automatic on first run or port changes as Windows will prompt to "allow this traffic") .

Also important is the ports to send and receive must be different, and must match across OSC applications.

GremlinEx supports the complete OSC protocol so can read/write OSC messages including string, integer and floating point parameters. It's important that GremlinEx and the other end "speak" the same command, which is beyond the scope of this document.

While GremlinEx can send OSC data with no parameters, it was discovered that the OSC layer in Bitfocus Companion does require a parameter even if the command does not use one. The value is ignored on the Bitfocus end but it doesn't function without it.

GremlinEx traffic

GremlinEx sends UDP traffic over a broadcast UDP which is not routable (by design). This avoids UDP packets sent by GremlinEx to be transmitted outside the local network. This requires its own port.

MIDI input

GremlinEx uses the MIDO Python libray to handle MIDI

Graphical interface

GremlinEx uses the QT library for the user interface. Specifically is uses the Pyside 6 library for QT. QT is quite elaborate as a user interface library, however has a pair of limitations encountered "the hard way" due to the highly dependent nature of GremlinEx to asynchronous inputs and multi-threaded approaches: the first has to do with QT Events that, currently, do not scale particularly well in performance tests to handle non UI related events. The other has to do with QT having its own garbage collection mechanism in C++ to manage its memory allocation which is entirely separate from Python's Pyside implementation. As a result, the experience has been that both memory managers/garbage collectors often gets out of sync, even with references enforced on the Python side, the primary issue being the C++ side removes objects still referenced by Python: this has led through GremlinEx's development to numerous bugs and issues ranging from hard exceptions, to race conditions, to memory allocation and unexpected null references.

Both are mitigated by not using the QT Event model. The second directly leverages the Shiboken API to validate the state of C++ objects on the QT side in case they are no longer valid, but still valid on the Python side.

General architecture and profile setup

GremlinEx, handles multiple asynchonous concurrent events from hardware and the user interface, and is completely internally event driven and is a multithreaded application. GremlinEx can process hundreds of messages every few seconds, especially as linear input is prolific and can send hundreds of events in a very short amount of time.

Triggers

GremlinEx has the concept of triggers. A trigger is an event that occurs whenever an input changes. For linear inputs (axis or fader), the trigger is whenever the input sends a new value. For buttons (or states), there are two triggers possible, one on press, one on release.

Some triggers are press only, for example, most rotary encoders and indeed some three way switches only send a "press" but no "release. GremlinEx has a mechanism to automatically configure a release, called an auto-release, if the situation calls for it. This is because most mappings require both a press and a release, so a "fake" release is created if the situation demands it. This makes rotary encoders function like normal buttons.

Action mappings and containers are generally aware of two triggers for momentary inputs. As such, most provide the ability to do different things if the input is pressed, or released. Most actions can execute only when the input is released.

So some actions can be set to respond only on an input press, and others only on an input release. Some do both and automatically generate a release depending on the input and required behavior.

Some actions or containers can consume the event and not pass it along. This is for example the case for condition evaluations, and mode hierarchy processing.

General execution logic

GremlinEx differs significantly from the original Joystick Gremlin project in its execution method. When a profile starts, GremlinEx builds a precompiled execution graph (known as a DAG - directed acyclic graph), that includes all possible event paths for each possible event, condition, device used and mapping. Each node in the tree keep stores the data and logic needed to evaluate a go/no go or execute decision without the need to search for data, and nodes are duplicated for speed where required if branching is involved. The DAG is constructed so the execution path includes part of the path all dependencies. This allows for very quick evaluations at each level of the tree is a dependency to the next level, so short-cut evaluations become possible as if a node fails the "go/no-go" test, the rest of the path in that branch is just ignored and the event is passed on to to the next branch that hasn't been evaluated yet.

The tree also uses priorities of each mapping to establish the execution order. For example, if a curve is applied to an input, that curve node is executed first so dependent mappings get the curve values, even if the curve node appears after the mappings. The priority is hard coded in each plugin.

When an input arrives in the form of an event, it is fed to the tree recursively to all paths until one of four things happen:

  • the tree evaluation for that node/level is a "no-go", so consumes the event (example a False condition) in which case subsequent child actions are just skipped and never get evaluated (shortcut evaluation).
  • the evaluation is a decision node and receives a "go" - it moves along to each child in the path for further evaluation
  • the evaluation is an execution node and "triggers" the mapping - it is consumed but results in one or more executed actions.
  • the event is ignored completely (the event doesn't match anything the profile cares about - and that decision is made close to the root of the tree to avoid evaluating leaf nodes)

Executed actions can trigger their own events as a result of being executed, and each generated event gets fed back into the tree for evaluation as it if was a standard input. This is used, for example, for auto-releases and to trigger multiple virtual inputs (so one event can end up creating multiple other events). This is also what enables GremlinEx to implement a state machine, as the execution handles "real hardware" and "virtual hardware" or events exactly the same way.

This architecture is a loose implementation of the shortest path algorithm - meaning that events are executed as fast as possible in a branch relevant to that event and any dependencies with as few decision points as possible. The execution tree is pre-built at profile start and includes all possible paths an event can take, based on the profile configuration.

GremlinEx supplements the execution graph by using pre-compiled lookup tables extensively to rapidly locate necessary information rather than have to go hunt for it at runtime. Most data searches are expensive to do at runtime, especially with large profiles or profiles with many states and conditions. The lookup tables become extremely important at runtime to access references to various information the runtime environment needs, and the concept, as with the execution tree, is to build once, use many times.

This also explains why GremlinEx uses a lot of GUIDs (globally unique identifiers) to represent all logical items in a profile, from an input to an event to a container to an action to a device. These IDs are used as an index in the lookup data.

As a result, most processing of events in GremlinEx is measured in milliseconds, including complex ones like Gated Axis, and the execution speed is usually not dependent on the complexity of the profile. Most events are processed in under 10 milliseconds (speed of course is dependent on the hardware used) and the number of execution nodes evaluated is usually quite small as events are discarded as quickly as possible.

First of all, as this has been asked, GremlinEx is NOT:

  • a keylogger
  • a virus or malware

You tell GremlinEx what you want it to do, by itself GremlinEx does nothing. You control the input and the output and where it goes. GremlinEx does not by itself record keys unless you tell it to listen to input, and you decide what it does with that data. Clients also have to be configured to enable remote-control.

Any security concerns can be alleviated by reviewing the open source code and compiling/running the code for yourself directly from Python. This does require the installation of a Python environment, as well as the installation via PIP of all the dependencies (requirements.txt file is provided for this purpose). This documentation will not go into how to setup a Python environment as this is outside of the scope of GremlinEx and a software development topic. GremlinEx releases come as pre-pacakged, easy to use and ready to use executables that includes all dependencies and ready to go.

The virus reference comes from the unfortunate mishandling of PyInstaller packaged Python executables (resulting in an .EXE from a python script) by some antivirus solutions. This, as far as I can tell, still hasn't been fixed after years (decades?) by some "legacy" anti-malware software which is disconcerting. The issue is widely documented and discussed (do a web seach on PyInstaller and virus false-positive) and indeed resolved by most anti-virus providers.

GremlinEx passes the VirusTotal checks, and the Microsoft Defender checks, and is not responsible for false-positives. This said, if you have any concerns, please be sure to run the software as packaged through multiple scanners and consult with a security specialist.

It should be noted that Gremlinex at its core is a (large) python script. The compiled version is through Python features and the Pyinstaller library which are both Python features and not related to GremlinEx.

As noted, GremlinEx is open source, it was writen with the best of intentions to solve common simpit problems, it is very security conscious and is an open book for this reason.

UAC (user access control) and firewall considerations

Windows 11 can cause some issues if GremlinEx is located in one of the system protected folders like "Program Files". Recommendation: use a folder "GremlinEx" to unzip the files to, that folder should not be in "Program Files" or "Windows" or any of the protected system folders.

Windows 11 security can also get in the way of sending output to specific processes as the default security setup lets you send keys to the active (focus) process only. Windows 11 may prevent GremlinEx from sending output to certain processes depending on group policies and account permissions, both are outside of the scope of GremlinEx as security is set at the operating system level. The default configuration for a typical user account on Windows 11 works well with GremlinEx.

GremlinEx sends keyboard and mouse commands you map via the Windows API to other processes. While in most cases it is not necessary to run GremlinEx as an administrator, some group policies and Windows configurations may prevent this output to go to other processes. This is not an issue with GremlinEx but a feature of the Windows API GremlinEx uses. This is not normally a requirement in testing. However it can also materialize itself with using tools like HIDHide, ViGEM and VJOY for the same reason, depending on what group policies and account restrictions are setup on your particular system. Most home users do not have this issue provided that you are allowed to install software and configure ports. Some enterprise users may run into this issue depending on the settings setup by their IT department.

When GremlinEx attempts to open a port, Windows will prompt the first time to allow this, and allow GremlinEx to communicate on the network. This is automatic and should be accepted or GremlinEx will not be able to communicate with OSC, BitFocus or other GremlinEx instances.

General Q&A

Question Answer
Do I need to install Python for this? No. The packaged version (zip) includes all you need.
Outside of GremlinEx, what do I need? You will need to download and install HIDHide, and download and install VJOY. Optional components include Bitfocus Companion (to manage certain input panels) and VIGEM if you want to output to virtual console game controllers (xbox 360 emulation).
Will this conflict with another Python installation on my machine? No. The packaged version (zip) includes all you need and will use the built-in runtimes and not use any existing Python environments you have setup.
What devices does GremlinEx work with? GremlinEx works with any game controller visible to Windows via the DINPUT standard. This includes most if not all devices that report as an HID USB game controller.
Do I need to run my joystick hardware manufacturer's software like T.A.R.G.E.T or Virpil? No. The device should function as a basic game controller without any software just by plugging it in. Some devices however need to be configured to look to Windows like a gamecontroller to enable different features such as axes and buttons and hats. This is programmed in their firmware by the manufacturer's software and not done by GremlinEx and should be done only once to enable all the features if it does not come factory set like this. In most cases this step is not necessary. GremlinEx handles all of the input mapping for all these devices regardless of the manufacturer. The requirement is the device must shows up as a DINPUT device.
How do I get started? Download the software, run it, and do a simple mapping. This documentation should get you started, however if you need help, visit the GremlinEx Discord community and ask questions! There is a forum on bindings, one on how-tos, and a general support/testing channel.
What's HIDHide and why do I need it? HIDHide is a tool that "hides" the real game controllers mapped by GremlinEx to VJOY virtual joysticks. You whitelist the GremlinEx process in HIDHide, and other processes including Windows won't see the raw hardware. This makes sure that games so it will not be confused with multiple concurrent inputs and only see the VJOY devices.
How do I use a Streamdeck with GremlinEx? GremlinEx uses the OSC protocol to communicate with devices supported by Bitfocus Companion including the Elgato devices and devices by other manufacturers such as a Loupedeck. Bitfocus (also free) replaces the Elgato control software and lets you map on theser hardware panels buttons and rotary buttons to OSC messages sent to GremlinEx. If you need help configuring Bitfocus and GremlinEx for OSC, please head over to the Discord channel.
What is remote control? GremlinEx is able to control other GremlinEx instances over the local network. This can be a single client, or multiple clients at once. This allows you to route output to these clients and that routing can be enabled / disabled by the profile. This helps when running games on multiple machines. Each client does need to have HIDHide and VJOY installed, and GremlinEx must be running on each, be configured for remote control (option enabled), and a blank profile should be executing. You can also have hardware on different clients send messages to the primary computer running GremlinEx such as over OSC so you can send axis, hat and button data that way as well. GremlinEx clients can send and receive data at the same time so they can all talk to each other in real time.
What about performance? In most cases GremlinEx can process inputs and convert them to outputs at runtime in under one millisecond, and certainly all under ten milliseconds even on network connections.
Can GremlinEx generate keystrokes? Yes. Use the map to keyboard/mouse EX action to generate keystrokes, mouse buttons, mouse wheel events, and access even special keys like F13 to F24 and volume control keys.
Can GremlinEx generate mouse output? Yes. For motion, use the Map to mouse/Ex action. For buttons including wheel, use the map to keyboard/mouse EX action.
Can GremlinEx split up axes into buttons or sub-axes? Yes. Use the gated axis action attached to an axis to split up an axis into button triggers (which can be directional), or range (linear) triggers to rescale an axis, create deadzones or special "gates" on an axis.
Can GremlinEx work with touchscreens like GameGlass? Yes. The touchscreen has to be on a separate machine (Windows limitation), and run someting like Open Stage Control to send OSC messages for axis and buttons to GremlinEx. Open Stage Control is a free app that lets you design input panels exactly like Gameglass. You can also use OSC output from GremlinEx back to the touchscreen panel to control its state? OSC is a network protocol developed for hardware and software stage control (so things like lighting systems, musical instruments, network connected actuators) and used here to communicate easily with various hardware and touchscreen (interactive) components.
Can GremlinEx work with MIDI control systems? Yes. GremlinEx supports MIDI in the box and can accept axis (linear) and buttons from a MIDI controller attached to the local machine, or via the network using things like RPTMidi. While MIDI is an old protocol for musical instruments, its use here is to be able to use controllers with faders, rotary encorders and buttons as input systems for games.
Does GremlinEx work with Microsoft Flight Simulator? Yes. GremlinEx includes a WASM module for MSFS 2024 and you can send axis and buttons directly to MSFS via its API, including run calculator expressions for special add-ons that have variables and controls not available via the Simconnect API.
Is GremlinEx hard to use? No, but that's up to you and the level of complexity you want to have in your profile. The basic mapping functions are very simple. You pick a device, you pick an input from the list, you add an action to that input, and tell GremlinEx what you want to happen. Save, run the profile and that's it. GremlinEx also has many advanced features such as advanced curving of inputs and outputs, calibrations, profile modes, profile states, axis merging, key latching, conditions, sequences, macros, axis splitting and gating, remote control, a KVM function, input and output from/to network devices and hardware panels like a Streamdeck and touchscreens. The most advanced is the custom plugin that requires knowledge of Python and the GremlinEx API. Just because the features are there doesn't mean they need to be used. No, you do not need to create five profile modes and ten states to manage your avatar's walking profile! You can if you want to, that's the point. Advanced features vary in learning curve, with a heavy emphasis on, usually not needed for basic usage although not difficult to use. The GremlinEx Discord community is available to help so ask questions and has a lot of screenshots and examples of typical how-to. Each situation is different so please, ask a question!
How do I map X? You'll find that in GremlinEx there are multiple ways to do a mapping ranging from simple to more advanced and conditional. Usually it's very straightforward and simple. This documentation has a list of the building blocks that can be found here for containers, and here for actions. Each is also described individualy the usage section of this documentation.
Why GremlinEx? GremlinEx is an integrator and stand-in for multiple solutions. It's designed to be a one stop shop for all hardware and software controller needs. It has a swiss-army knife of options when it comes to various ways to take inputs, manipulate that input, and create meaningful outputs for simple games to very complicated simulators with lots of controls. GremlinEx is for single joystick scenarios to full hardware network enabled cockpit setups.

Troubleshooting

The GremlinEx Discord community is a great place to ask for help, report issues and get how-to answers.

Typical issues

GremlinEx warns me this is an unknown publisher

Windows will generate this warning the first time you run the packaged GremlinEx. This is because the packaged application is not signed. If you are concerned by this, you can always run this Python application from the source code and create a package for yourself. GremlinEx comes pre-packaged as a convenience as it's not expected that everyone will setup a development environment and dependencies on their system. However it is definitely an option if this warning box is a concern. GremlinEx is an open source project and all sources are available as an alternative.

GremlinEx gives a startup error

Startup errors usually are due to missing components or incompatible components. GremlinEx includes all it needs in the distribution package (zip), including the correct version of the Python runtime needed and any support DLLs needed. To this end, when installing a new version, make sure you delete any prior files (if installing in the same folder). The log file %userprofile%\joystick gremlin ex\system.log will contain any critical errors. GremlinEx includes all it needs and is self contained.

Another cause of a startup error may be security related, specifically, insufficient permissions on the account to run. This is rare.

GremlinEx is unable to communicate with clients on the network

Make sure that the port is configured the same for all clients (6012 is the default). When GremlinEx first runs and remote communication is enabled (either to send/broadcast or receive), you will get a Windows prompt to authorize this in the firewall. If you denied the request, you will need to manually enable the port in the Windows Firewall settings.

My devices show all disconnected (or do not show at all)

Suggestion Description
Check HIDHide configuration Make sure HIDHide is whitelisting the gremlinex.exe process. If you have multiple versions installed (for testing for example), ensure that each executable is white listed.
Firmware, driver updates or USB connection changes for your physical joysticks. It is known that firmware and driver updates from hardware vendors change the unique device GUID of each device. Connecting your device to another USB port (or hub) can also change device GUIDs. Profiles created with older GUIDs need to be updated which can be done by grabbing the new GUID from the GremlinEx device information dialog (copy to clipboard) and do a search/replace in the profile XML data to swap the old ID with the new. Make a backup copy of the profile XML first, and use an editor like Notepad++ to make the changes as this editor will show XML properly with syntax highlighting, which makes the process easier.
Device is asleep Some older devices tend to go to sleep if not used for a period of time. There are ways to prevent Windows 11 from placing them in standby / sleep mode via Device Manager. There are multiple online articles on this subject if this happens to you. The symptoms are - devices are visible when you first boot the computer, but go offline on their own after a while.
Device is not a DINPUT device GremlinEx can currently only see DINPUT compatible devices, and most HID game controllers are. Some may not report as a game controller and are incompatible with DINPUT. Some devices like touch screens and the Elgato Streamdeck are not DINPUT devices but can be used with GremlinEx via the OSC protocol and the use of BitFocus Companion.

User interface is blank

This usually indicates an internal exception occured. You can change tabs, close GremlinEx and re-open and see if the issue persists. Please report these to the GremlinEx Discord community channel. There may still be a dragon in the software to look into. Be ready to provide the log file and screenshots if requested, including the GremlinEx version number. Patches can be frequent and it's highly possible an update has resolved the issue already. Check for updates frequently in the release section of the project GitHub page. The log file is located at %userprofile%\joystick gremlin ex\system.log.

Nothing is happening (or the wrong thing is happening)

Suggestion Description
Profile must be running GremlinEx only creates output if the profile is running.
Make sure you are using the latest stable version of GremlinEx GremlinEx is regularly updated when issues are reported and resolved, so be sure to run a current release and check Discord/Github regularly for any updates.
Ensure the input is triggering Ensure the input is registering in GremlinEx, for example using the Input Viewer. If GremlinEx does not detect an input, there will be no output.
Check profile modes If you are using multiple modes in your profile, ensure the profile is in the correct mode, and selects the correct mode at startup.
Check the output outside of the target application Sometimes using the target application to check outputs is not helpful as it can be the target application iself not registering inputs.
Use a keyboard checker to look at output mouse buttons and keystrokes outside of the game. Use a tool like Thrustmaster's Event Checker (part of T.A.R.G.E.T) or a free keyboard checker utility like YAKD or Keyboard Key Info. These will show you what keys (and mouse buttons for the TM tool) are output by GremlinEx. This eliminates any issues with the target game by verifying that GremlinEx's output is what you are expecting first. This is particularly helpful with timing issues.
Use VJOY Monitor to validate joystick outputs. VJoy Monitor is one of the utilities that comes with your isntallation of VJOY and it shows the status of each vjoy device in real-time. You can also use the built-in GremlinEx Input Viewer, however VJOY Monitor runs as a separate process and verifies that VJOY is being programmed by GremlinEx correctly. This will help identify where the issue may be - with the profile - or with the target application's mapping.
Use the GremlinEx Input Viewer The Input Viewer dialog can show inputs, and outputs as well for quick checks.
Use verbose options GremlinEx as a comprehensive set of verbosity options to enabled certain subsystem output to the log file. This is helpful to troubleshoot a specific input or output as you can isolate issues that way easily. There are separate verbose options for VJOy, macros, keyboard and mouse, as well as OSC. These options can generate a copious amount of data to the log file %userprofile%\joystick gremlin ex\system.log so only enable the options you need when troubleshooting inputs or outputs.
Use a small, new, test profile It is best to setup a simple test profile to check the input and action configuration. It can be difficult to troubleshoot a complex profile so simplify the task by breaking it down to manageable pieces to validate each issue separately.
Ensure the output isn't happening too fast or too slow. Many games use a loop to read inputs, and there are two scenarios: The output generated by GremlinEx is too fast: most button and key presses require about 100ms to register with a game. It does vary with the application, but if you have an output that triggers a key press, and 4ms later triggers a release, the game may not see that key (button) at all. Conversely, some games cannot detect sequence of keys if they occur too slowly, and the sweet spot for this tends to be around 250ms between a press and a release (for games that expect a momentary action like a single key press or a button press.)
Ensure the mappings on the target application are correct. Ensure HIDHide "hides" the raw inputs you are processing via GremlinEx so the target application isn't confused by two concurrent inputs (raw plus the one generated by GremlinEx). The target application should not be whitelisted in HIDHide. Also ensure the application is mapped to the correct VJOY device. Because they are (unfortunately) all named the same, it can be difficult sometimes to map to the correct VJOY device because the order they appear in the application may not be the order of the VJOY device ID.
Ensure you rebooted the machine at least once before designing a profile so the device order from a game's perspective is repeatable. Windows changes the order of devices (that includes VJOY devices) at boot time and runtime, and the order is not going to be repeatable until you reboot the machine after connecting a device. To this day Microsoft does not allow end-user game controller ordering in Windows. This happens usually when you connect/disconnect devices while Windows is running, and this can confuse the target application to no-end. GremlinEx doesn't usually care because it uses the unique hardware GUIDs, not the order of devices, but the same is typically not true of many games. In particular, VJOY devices can have their order change, so what you see as device 1 may not be device 1 in the game. Microsoft Flight Simulator is one of these applications that gets confused with that as of this writing. So if you are using multiple VJOY devices, know that the first one in the device list on the game side may not be the device you are expecting. Rebooting the machine (with the devices connected) ensures that device order will be steady - hence why it is not recommended to keep on disconnecting/connecting devices to the machine because it usually leads to device ordering problems outside of GremlinEx. If you connect (reconnect) anything - you have to reboot the machine after you do to avoid problems.

General support

Please consult the Discord server for community help and discussions on everything GremlinEx related.

Things will go sideways. That is the nature of the simpit experience. If a bug or issue is encountered, please file a GitHub issue and take screenshots and describe the issue as best as you can. "It doesn't work" is usually not very helpful

You can also post constructive commends on issues encountered Discord testing and bug discussion forum.

GremlinEx is complex, and bugs may come up especially with test releases. Be ready to provide screenshots, the log file with some verbosity settings enabled, and describe, as best as able, a way to reproduce the issue. There are some issues that are specific to a hardware device that may be more difficult to reproduce, and the majority of bugs are not random.

GremlinEx is a tool designed to solve problems, not create them, and know it's created as a hobby from a single dev passionate about simpits and hardware mapping - representing hundreds of development hours built on prior project work from others that also took hundreds of hours. I will make all attempts to resolve the issue or suggest a workaround as able. Please be nice, courteous and be patient with issues as they occur. Some may be quick to resolve, some may not.

Many of the features in GremlinEx come from my own experience with a wide variety of tools in this space used over the years, and from ideas from the community "I wish it did...".

I hope you enjoy this tool as much as I enjoy making it.

Muchimi