0
\$\begingroup\$

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?

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

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.

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_array from 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_array from 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.

\$\endgroup\$
2
  • \$\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\$ Commented 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\$ Commented Aug 19, 2020 at 17:12

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.