I am using the d3d model creation functionality in Game Maker. I also use dlls and I want to be able to modify a 3D model (change uv values) without recreating a model. Is there a way to locate the address of the model’s memory and use pointers to directly change the values? Is this possible and how would I go about doing it?
1 Answer
There is not a built-in function for this. In GameMaker: Studio and newer, you would probably use buffer_get_address and pass the updated buffer to vertex_buffer_create_from_buffer, but in GM8.x (which the question author uses) that was not yet a thing.
What follows requires a degree of determination.
First you would want to find out an address of a built-in d3d_model_* function. I'll use d3d_model_clear here since it's one of the more straightforward ones.
- In GM8.1 you would want to use
function_get_address. - In GM:S you would want to use this trick I came up with.
Despite the amount of rewriting behind the scenes, the function stayed quite alike:
First it
CALLs (opcode E8) a function to pull out an integer out of the only argument.Then it
CALLs (E8 again) the implementation.The implementation goes like this:
void internal_d3d_model_clear(int index) { if (index >= 0 && index < internal_d3d_model_count) { // internal_d3d_model_array is an internal_d3d_model* internal_d3d_model* a_model = internal_d3d_model_array[index]; } }which in assembly means
TEST index, index <JS or JL> ... CMP index, internal_d3d_model_count JGE ... MOV a_model, internal_d3d_model_array // +index*4 here or in next instruction
With the function address in your hands you could either:
- Simply connect Visual Studio debugger to the game (Debug > Attach to Process), look at disassembly, and copy the fixed location of
internal_d3d_model_arrayfrom the MOV instruction. This will not work when changing GM versions - Use an instruction parser (like this one) to have it dynamically extract the location of
internal_d3d_model_arrayfrom the inner function.
Once you have that location, you can dereference the array pointer from it (your_d3d_model_struct* d3d_model_array = (your_d3d_model_struct*)(*(int*)that_address)) and start investigating what is stored inside each model using the memory viewer or Watches window in Visual Studio - considering the circumstances, I would guess that there is another pointer to either raw vertex buffer data or an array of structs representing diffferent primitive operations.
- \$\begingroup\$ One question. Is the “internal_d3d_model_array” going to stay the same each time one makes a game maker program? That is to say, can one utilize that address as a constant once it is known (of course thereby being locked to that version)? \$\endgroup\$user64742– user647422020-08-18 23:04:43 +00:00Commented Aug 18, 2020 at 23:04
- 1\$\begingroup\$ The address will remain constant for non-YYC builds made with the same version. For YYC, it may or may not be constant as the runtime is being linked dynamically against the transpiled game code. Pre-Studio builds count as non-YYC. \$\endgroup\$YellowAfterlife– YellowAfterlife2020-08-19 17:12:44 +00:00Commented Aug 19, 2020 at 17:12