YAL-GameMaker/shader_replace_unsafe (2024)

Quick links: documentation· itch.io
Versions: GameMaker 2022+
Platforms: Windows, Windows (YYC)

Hey! Feel like you need a little danger in your game development?Tired of extensions that Just Work?

Well look no further, 'cause this extension could spontaneously combust at any moment.

But it's not just about catching fire, think about the advantages: this extension can load new shaders at runtime! And not just replace a shader with an equivalent one like shader_replace_simple does, but actually add a brand new shader that will work just like the existing ones - complete with uniform functions and all that.

What's interesting here

For this extension, "interesting" is certainly a good descriptor.

Loading a shader at runtime requires a huge pile of boilerplate code (there are multiple steps, and each one may fail), but that's not all!

To make a shader behave like a built-in one, we have to add it to a built-in shader arrays too!

And no one's going to just hand it to us, so we have to find it inside built-in functions!

And that means parsing raw CPU instructions with a slightly-obscure Windows DLL!

And only then we can replace the built-in shader arrays with our own that we can expand.


(click to expand)
Once upon a time, I thought that it could be cool to let people load shaders in Nuclear Throne Together.

Originally purely an online multiplayer mod, over timeNTThas grown to have its own mod loader, accumulatinghundreds of modsand leading to me being hired to work on Nuclear Throne itself.

And it was cool.

Although shaders had to be written in HLSL9 (and, later, HLSL11),combined with vertex buffers it meant that you could do a whole lot more drawing tricks than before.

But there was a little caveat: I used an extension for it that ceased to work when the game was updated to GameMaker Studio 2.

GMS1 used DirectX 9 while GMS2 used DirectX 11(meaning that DLLs targeting D3D9 wouldn't work),though there had also been major changes to graphicspipeline that I didn't know of at the time.

And it was also a busy time for me.

I had just moved to Odesa, and, surely enough,was working on at least 3 big projects.

So, after making a few prototypes with varying degree of success, I tried to hire someone to do this.

Surely enough, if something wasn't easy to do for me,it wasn't going to be easy to find anyone to help with this.

Sometime around the end of the year I finally managed to finish the work myself after getting some advice on D3D11 specifics

Unknown to me, someone took my seeming lack of progress as an invitation to have a shot at the task.

They later admitted that they thought that I'd abandon the idea after seeing someone else accomplish this.

... and later begged me to not bundle my extension for free with GMLive, not to destroy their odds of selling theirs.

(although this was a little silly - GMLive is one of the more popular GameMaker extensions, but I doubt that even 0.1% of all GameMaker users own a copy of it)

So I agreed to release my simpler extension as "pay $10 or ask for a key" and not release the bigger extension until they release their extension.

The simpler extension is what became shader_replace_simple.Roughly 15% of its users requested a free copy, which is less than I was expecting.

The bigger extension was the precursor of this one - the ideas were much alike, but it was much jankier. It was only used in Nuclear Throne and another work project that never saw the light of the day.

And then they never released their extension.

The motivation is unclear, though they did mention that they feltlike simplifying game development too much was harmful to the industry as a whole, so maybe that's what it is.

I finally removed the link to their work-in-progress thread from GMLive documentation over two years later.

Then GameMaker Studio 2.3 came along, and everything changed.

Ability to get pointers to structs and methods meant that you couldfinally acquire pointers to built-in functions without going throughridiculous hacks.

And GM2022's (still very poorly documented) YYRunnerInterface allows functions to work with GML values directly - without the usual interop costs.

And my extension stopped working in GM2022 due to transition to x64 Windows runtime, so I figured that it's just about time to rewrite it using new tools at hand.

My original implementation used a modification of this snippet, which was x86-only and was missing some of the extended instructions.

In the remake I took the opportunity to rewrite the code to use DbgEng, which appears to be primarily aimed at low-level and driver developers, but also this is your best bet at decoding instructions without bundling a huge library (like Intel XED) or staring at Intel's instruction reference for no less than a few days.

And, of course, function pointers and my advancements in tooling (GmxGen and GmlCppExtFuncs) meant that there's far less boilerplate to write.

And now we're here.


See BUILD.md


Author: YellowAfterlife
License: Custom license (see LICENSE)


Loads shaders at runtime... dangerously



Language:C++ 70.8%Language:Game Maker Language 18.6%Language:Batchfile 4.9%Language:GLSL 4.8%Language:C 0.7%Language:HTML 0.2%

YAL-GameMaker/shader_replace_unsafe (2024)
Top Articles
Latest Posts
Article information

Author: Kelle Weber

Last Updated:

Views: 5331

Rating: 4.2 / 5 (53 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Kelle Weber

Birthday: 2000-08-05

Address: 6796 Juan Square, Markfort, MN 58988

Phone: +8215934114615

Job: Hospitality Director

Hobby: tabletop games, Foreign language learning, Leather crafting, Horseback riding, Swimming, Knapping, Handball

Introduction: My name is Kelle Weber, I am a magnificent, enchanting, fair, joyous, light, determined, joyous person who loves writing and wants to share my knowledge and understanding with you.