GithubHelp home page GithubHelp logo

yal-gamemaker / function_get_address Goto Github PK

View Code? Open in Web Editor NEW
8.0 2.0 1.0 30 KB

A trick for getting pointers to built-in functions in GameMaker Studio (versions 1.4.1773 - 2.2.1.191)

Game Maker Language 6.56% C++ 70.68% C 22.76%
gamemaker

function_get_address's Introduction

function_get_address

Supported versions:

  • GameMaker: Studio: all versions released after 1.4.1773 (object value type wasn't supported before then)
  • GameMaker Studio 2: all versions before 2.2.2 (2.2.1.291 is the last one where this works)

For GMS2.3 and GM2022+, check out the 2024 edition.

What is this

This trick allows to acquire a pointer to a native GML function, as result allowing you to pass it to a native extension and have the later call it - for example, your extensions now can suddenly make buffers, or data structures, or even call GML code (to an extent)! A true extension rennaisance for the affected versions.

How this works

Let's take a look at the heart of the system, the function_get_closure script

var name = argument0;
variable_global_set(name, variable_global_get(name));
return ptr(variable_global_get(name));

So you might be wondering what is even going on here.

In what is most likely to be what remains of some delayed or scrapped feature, recent versions of GameMaker kind of support C closures for built-in functions.

Except you can't get them because the global scope isn't populated with built-in function names.

However, as an accident revealed, the way the built-in functions are expected to be set into scope, is that the scope needs variables defined with names but no values - not just undefined, but the special kind of value that resides in variables that were never assigned (kind==VALUE_UNSET on YYGML.h terms). And you can't just get such a value by passing an nonexistent variable to a function (which would give you a read error) - the value must come from a GML function call.

This is where variable_global_get comes into play - due to a bug that hadn't been fixed until GMS2.2.2, if a nonexistent variable is being read via the function, it would return the exact thing that we need.

And thus, variable_global_set(name, variable_global_get(name)); will generate an index for a global variable while keeping it amiss, which allows the subsequent call to create a closure and return it, which we can get a pointer of.

Then, on C side we can grab the actual function pointer from the closure, call (or store) it accordingly, and voila!

We can then add a bit of caching and a couple C++ wrappers to make it all nicer.

Limitations

  • You cannot get a pointer to script_execute specifically because it got optimized and is no longer a function as such (that's why it's so fast)
  • It is unclear whether and how you could get pointers to GML instances for use in C code.
    For the most part, you don't need to, as you can use variable_instance_ functions to work with instances, but calling instance-specific functions (which require valid self/other pointers) is problematic without these.
  • You can call GML code via event_perform_object, but you'll need to construct something resembling a valid GMLInstance first (feel free to research alternatives).

Special thanks

Saturnyoshi for gml.h file (as seen in UGMMS), which allowed me to not write another one of these for this mini-demo.

If anyone from YoYo Games is reading this

A built-in function_get_address would be nice, even if it was native-only (no HTML5) until further notice (besides, it's pretty trivial to get function pointers in JS anyway).

function_get_address's People

Contributors

yellowafterlife avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

gm-archive

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.