ENIGMA Development Environment
Website is in read-only mode due to a recent attack.

The Grand To-do List

odo - ENIGMA Development Environment

This is a list of all the current things needed in ENIGMA. Developers can use this as a guide for things they could consider doing. General users can use this to know what things aren't functional yet in ENIGMA.



ENIGMA bugs and suggestions can be found on the Github Tracker Page

Task Lists

Tasks are also on the ENIGMA tracker page.

2019-2021 Roadmap

  • Grow the CI coverage by another 25% over the next year. This includes completion of binary buffers and testing of them. Coverage of objects, inheritance, and collisions.
  • Continue improving and maintaining the ENIGMA engine and LateralGM. This includes new features and smaller fixes as users request them.
  • Finish the EGM writer thus completing the EGM library. Test EGM project serialization to keep it working.
  • Finish refining the asset compilation stages so that emake becomes a functioning remote asset compiler. This includes finalizing ideas of how RadialGM and the like should attach assets to the exe locally or remotely.
  • Continue developing RadialGM into a stable and usable IDE. This includes completion of additional editors, refinement, and integration of the above completed APIs.

Debug Code

Because everybody is lazy, a lot of functions are missing debug code. So there's plenty of easy work to do here around the place, adding in checks for when debug mode is used.

Ultimate Goals

A bunch of other things need done to get ENIGMA ready for serious game development.

Code Export Revamp

To decrease build times in succession, we need to look into separating the main header from engine code and placing individual objects in their own source files. The main header, which is currently the main source, would be moved into its own file apart from compiler-exported code, then ideally be pre-compiled. Another option is to have object files built for each object in the game packaged into the EGM to facilitate faster building between runs of different games.

With the ability to compile objects separate from each other comes the ability to compile objects during run time and link them in dynamically, which will facilitate hot-swapping code in debug mode, as is a feature in other IDEs for other languages. Since instance_create will have to be refactored to call a function to create an object with a certain index, and in all likelihood, so will dynamic dot-access functions, it would not be a difficult matter to replace the code which allocates obj_character with code to allocate a new object of that type, as loaded from a DLL. The dot-access system may, in turn, need to be less efficient when compiled in Debug Mode to facilitate this hot-swapping.

File Storage Revamp

In order to enable ENIGMA to be placed in write-protected portions of disk, such as /usr/bin/ENIGMA or C:/Program\ Files/ENIGMA, main configuration files will need to be overridden by files of the same name found in ~/.ENIGMA, and objects will be exported and built to /tmp/ and then optionally copied to the EGM as mentioned above.

While this system is not necessary for the performance of ENIGMA, it accounts for a large piece of the distribution mechanism for ENIGMA. Linux packages and Windows installers, by convention, unpack into /usr/bin and Program Files. While unpacking to Program Files may cause issues due to the space in the pathname (that Microshaft has still not corrected, 20 years later), unpacking to /usr/bin is a must if we intend for package repositories used by major Linux distributions to allow installing ENIGMA on a fresh system.

Resource Revamp

We have this beautiful resource tree, but all your efforts organizing resources into it go to waste.

LateralGM loads all your resources into memory at startup, even for formats such as EGM which do not require doing so at all. Then, to make matters worse, ENIGMA adds them all right on top of the game, and loads them all into memory at once, too.

This system needs reworked so that resources can be stored externally—with or without encryption—and loaded into memory either on an as-needed basis, or, better yet, by resource group name as they appear in the resource tree.

For example, when you hop from the volcano zone of your game to the ice zone, you would call resource_tree_unload("Scenery/Zones/Volcano"), resource_tree_load("Scenery/Zones/Ice");. That would automatically unload all resources of any type found in the "Volcano" subtree of the "Zones" subtree of the "Scenery" subtree of the resource tree, loading instead the "Ice" folder from the same subtrees.

The idea is that the resources still remain segregate, but share an identical tree structure. So, the Sprites and Backgrounds resource trees may contain Scenery/Zones/Volcano, while the sounds directory does not. In regular GM6 view, the Sprites subtree will contain a Scenery subtree containing a Zone subtree containing other subtrees full of sprites, the Backgrounds subtree will contain a Scenery subtree containing a Zone subtree containing other subtrees full of backgrounds, but the Sounds subtree will not contain a Scenery subtree at all. In the universal view, the resource tree will directly contain a Scenery subtree containing a Zones subtree containing other subtrees full of sprites, backgrounds, and potentially other resources.

Objects may or may not be loaded dynamically as DLLs; the possibility of lazy-loading regular objects via the mechanism described in the code export revamp is something that should be investigated later on as well.

New Resources

It should be easy to add resource types to ENIGMA. Among the resources to be explored should be a 3D model resource and the Overworld resource discussed in the Proposals section of the forum.

Instance System Revamp

No globals should be used in the instance system which are not encapsulated by a thread class. The globals which control the "current" instance should not exist; they should be passed as parameters to functions which require this information. The lists of instances of each object should also go in a thread class. The instance_deactivate* functions should move deactivated instances to a dead thread class instead of whatever system TGMG used to implement them. Later, the thread class should be instantiated when the user tries to move objects to different threads. In general, only the events should be moved to a different thread; instance references should be left in the main game thread. The main game thread can be global.

Function Definition Revamp

We ought to move functions into a new namespace under enigma{}. The namespace can be either ::enigma_functions or ::enigma::functions. JDI will then assist ENIGMA in ignoring any C++ functions which are not using'd somewhere in the ENIGMA definitions. The ENIGMA {{include}} directive (not yet implemented) should be replaced with {{require}} and hint to the compiler to include the requested header, but not necessarily use it. This will also help keep code language-agnostic in the event that someone happens to create a JavaScript library called "map" or "vector" or "GL/gl.h".

In namespace enigma::functions, math and stdc functions required by EDL should likewise be adopted via (eg) using ::sin.

This removes the need for the Bessel function hack, which #defines each Bessel function to use a bessel_ prefix, then implements them in another source. Instead, the STDC Bessel functions will simply be ignored by ENIGMA and will need implemented as, eg, double (*bessel_y0)(double x) = ::y0;. This eliminates overhead and hacks alike.

Events.res Revamp

Events.res presently uses a custom breed of e-YAML that allows adding a default attribute to a group. We can do without that, which will allow the file to be plain e-YAML, and thus allow LGM/other IDEs to read it the same way they read everything else. Moreover, we need a way to just insert a call in place of the event, both in the event handler method and in the actual per-instance event loop.

The file also needs modified

Game Saving / Loading

One of the cooler perks of Game Maker is that the functions game_save and game_load create almost instantaneous dumps of your entire game's state. ENIGMA's compiler gives us the necessary control to implement these functions in the C++ engine dynamically. Here's what we need:

  1. ANYONE: Create a function write_dump with an overload for all ENIGMA primitive types, and as many STL types as possible.
    • The first parameter should be a FILE* or ostream, or a typedef to something platform-dependent.
    • The second parameter should be a const reference to the type mentioned earlier.
    • This function should serialize the given reference and write it to the given stream.
  2. ANYONE: Create a function read_dump with an overload for all ENIGMA primitive types, and as many STL types as possible.
    • This function should take identical parameters to write_dump, but use a non-const reference and load into it.
  3. COMPILER: Construct a save_binary(FILE*) function into each object.
    • This function should invoke write_dump for each local variable in the object.
    • We may want this function to write a header with a magic value such as char[4]("OBJ") so we know we're reading right later.
  4. COMPILER: Construct a static load_binary(FILE*) function
    • This function should create a new instance of the object, loading locals from the given FILE*.
  5. ANYONE: Make the game_save function iterate all instances, calling their save_binary method.
  6. COMPILER: Pack the load_binary functions of each object into an array, loader_array by object_index.
  7. ANYONE: Create a load_binary function in object_basic
    • This function should verify the object header, them read the ID and object index from it.
    • It should then use the object index to invoke the correct loader_array method.
  8. ANYONE: Make the game_load function call the object_basic load_binary until EOF.


In the sprite and background sources, eg, Universal_System/spritestruct.cpp, you will notice there are two macro functions to fetch a resource from its ID. For example, get_sprite vs get_sprite_mutable. This is to facilitate the implementation of threads later on.

When the time comes, these macros will place locks on the sprite data being accessed. While the sprite is locked for write, no other threads will have access. While it is locked for read, no writers will have access. By using the wrong macro, you will introduce unnecessary wait time that could potentially be noticed but never found.

We will also need a THREADS_ENABLED macro to avoid making single-threaded games place locks on that information.

Proposed Systems

This is a list of all the systems that have been proposed to use in ENIGMA

  1. Additional statements: when, step and draw -polygone suggestion
  2. Member functions
  3. Pause system