Execs DLL
by Score_Under (Charles Daffern).
Last update 19th February 2009. 3 new functions, still supports 4 versions of Game Maker.
The "asm.dll" included with this package is a version of the assembler included with OllyDBG made to be compatible with GM and Execs.dll, and is therefore property of Oleh Yuschuk.
The "cc3250.dll" is simply a runtime from Borland to get "asm.dll" to actually work.
"Execs.dll" is mine, of course! ![]()
OllyDBG is also useful to debug any mistakes you make with the machine-code execution functions of this DLL.
Compatible with:
This DLL contains many functions, including:
- Threads
- execute_string, for all above versions, also accessible from your own DLL (like an SDK).
- Conversion to hex (for ASM)
- Assembler
- Memory read/write/allocate/free
- Execute machine code in memory
First, some warnings.
Threads
DO NOT exit the process before the threads have finished. This will cause an access violation.
DO NOT terminate the threads with thread_end unless you really have no other choice.
DO NOT access local variables from the thread. It will crash the game.
Workaround: use "object0.x = 5" or "with(object0)x=5".
If your code is in a loop, ALWAYS put code into your thread to exit, for example, "if (global.exiting) exit;", to close the thread safely when you want to.
Memory / Execution
When executing a function - check what it returns. If it returns a double, then you will have to pop the FPU stack before returning your own value. If it doesn't return a double, you *must* add a command like FLDZ before the return.
NEVER overwrite more memory than you've allocated. ALWAYS allocate more than you need.
NEVER "lose" a pointer to still-allocated memory before freeing it.
NEVER free memory twice.
If your game crashes inside mem_exec, chances are it's your fault and not the DLL's.
ASM
Always remember to set_ptr!
Now, for some info.
If you do not wish to use any ASM functions, you can delete ASM.dll and cc3250.dll.
Info
Threads
thread_init() - Determines the version of Game Maker, and gets the correct handle to execute_string().
thread_exec(string,suspended) - Starts a new thread, executing the code in the string. Set argument2 to SUSPENDED to start suspended, or NORMAL to start straight away. Returns a thread handle.
thread_priority(handle,priority) - Resets the priority of the thread.
thread_suspend(handle,suspend) - Suspends or resumes the thread (set the second argument to either SUSPEND or RESUME)
thread_exists(handle) - Checks if a thread exists.
thread_affinity(handle,mask) - Sets processor affinity mask for a thread. "3" is processors 0 and 1.
thread_affinity(handle,processor) - Sets the ideal processor for a thread.
thread_count() - Returns the number of threads left. Slow.
thread_end(handle) - Abruptly terminates a thread. ONLY USE IF YOU CANNOT TERMINATE IT BY ANY OTHER MEANS.
unload_execs() - What you get if you apply thread_end() to all threads.
get_processors() - Returns the number of processors on the system.
is_slow() - Returns true if the current operating system believes that your computer is slow.
Memory
These functions were made to be used in conjunction with ASM functions.
It is possible you could assemble the code beforehand, however.
get_module_handle(name) - Returns the module handle for a module (e.g. get_module_handle("user32"); )
get_proc_address(module handle, procedure) - Returns the address for a procedure inside the specified module handle. (e.g. get_proc_address(get_module_handle("user32"),"MessageBoxA"); )
get_game_module_handle() - Returns the module handle for the GM game. Usually $400000.
get_gm_proc_address(name) - Returns the procedure address for any Game Maker built-in function. New! 19th Feb 09
set_gm_proc_address(name,address) - Sets the procedure address for any Game Maker built-in function. Use with extreme care. New! 19th Feb 09
load_library(name) - Loads a DLL into memory, returns the module handle.
free_library(handle) - Frees a DLL from memory.
mem_exec(address) - Executes the machine code at the memory address specified. Use in conjunction with ASM functions.
All read_* functions return the value read.
read_int(address) - Reads a 4-byte signed integer from the specified address.
read_str(address) - Reads a whole NULL-terminated string from the specified address.
read_uint(address) - Reads a 4-byte unsigned integer from the specified address.
read_byte(address) - Reads a single byte from the specified address.
read_double(address) - Reads a double (GM's "real") from the specified address.
All write_* functions return 0.
write_int(address,int) - Writes a signed integer to the specified address.
write_string(address,str) - Writes a whole string to the specified address.
write_uint(address,int) - Writes an unsigned integer to the specified address.
write_byte(address,byte) - Writes a byte to the specified address.
write_double(address,double) - Writes a double (real) to the specified address.
write_bin(address,value,length) - Writes binary data (like a string, but can have chr(0) in it) to the specified address.
mem_set(address,byte,length) - Repeatedly writes the specified byte to the address.
mem_copy(dest_address,src_address,length) - Reads binary data from src_address and writes it to dest_address.
mem_alloc(length) - Allocates length bytes. Returns pointer.
mem_free(pointer) - Frees a pointer. Always use once you've finished with your memory. Do not use on random addresses.
virtual_protect(address,size,new_permissions) - Changes the protection of a memory page. Used to avoid crashes with some ASM code. New! 19th Feb 09
ASM
init_asm() - Initialize ASM.dll
asm(string) - Assembles the ASM string to the current pointer, then increments the pointer by the length of the assembled code.
set_ptr(pointer) - Sets the pointer used by ASM.dll.
get_ptr() - Returns the pointer from ASM.dll.
to_hex(num) - Converts a number to hex, and if the first hex char is a letter, prepends "0".
If you need disassembly functions, PM me.
Writing your own DLL with execute_string
You only need to include "execs.dll" with your game. Call "init_execs()" from Game Maker, then after init_execs has executed, in your DLL, execute code similar to this:
(Works in all GM versions mentioned at the top of the post, and as always, don't set local variables without using a with(obj) or a obj.var statement)
typedef double type_execute_string(char*str);
int call_gml(char*a)
{
type_execute_string* exec;
exec=(type_execute_string*)GetProcAddress(GetModuleHandle("execs.dll"),"execute_string");
if(exec)
exec(a);
else
return 0; //failure
return 1; //success
}Example of usage: DLL 3D model reader - you can just sprintf() the values onto a GML string, which can be executed as "with (object){vertex[0]=13.55; vertex[1]=43; ...}", thus meaning only 1 DLL call and much less overhead.A final word:
This is not for the faint of heart. Especially not the ASM capabilities.
Download: >ZIP< or >RAR< for those of us who prefer a smaller filetype, even with the recovery record.
>ZIP Mirror<
Contains Execs.DLL, ASM.DLL, Borland C++ runtime DLL, 2x GMD, 2x GM6, 2x GMK.
You do not have to give credit. You may use this in commercial and non-commercial projects.
If you find any glitches, PM me right away, with the code that caused it.
Yes, I have been teaching X-Tra Fear.
Edited by score_under, 24 February 2009 - 08:21 PM.











