Please help me with syntax.

Hello friends,

I've made a DLL which I load into the Sonic Generations game process, which I'm using to learn how to move variables around and whatnot in the form of "cheats" for the game.

Using various debugging tools, I've found base pointers that store Sonic's XYZ location. I wanted to code a save location button, and a restore location button. The issue I'm having is writing it in C++, as far as getting and saving those values.

I know that a base pointer of 0x01E11C60 points to another pointer, which it plus 0x00000010 points to a final location, which that location plus 0x00000070 holds the X value, then 4 bytes later the Y, then 4 bytes later the Z value.

Should I address this like an array? How do I write a statement to save it, and a statement to reference it? Remember this is a DLL inside the process, so I don't need ReadProcessMemory or WriteProcessMemory.

This is what I have so far, which of course doesn't compile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int SonicXYZ[2] = (int*)((*(INT*)((*(INT*)((*(INT*)(SonicAddr)) + 0x10))) + 0x70));
int SavedLoc[2];

...

		if (GetAsyncKeyState(VK_END))   // Save location
		{
			SavedLoc = *SonicXYZ;
		}

		if (GetAsyncKeyState(VK_HOME))  // Restore location
		{
			*SonicXYZ = SavedLoc;
		}
I think this would work for you. I also think that ASM is the right tool for this kind of thing. If you know ASM, you can ussually do inline ASM commands in C++.

I'm using a structure for XYZ. The pointer math is done in the constructor which is automatically called when we create SonicXYZ. I hope it works!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct SonicXYZ
{
    int* x;
    int* y;
    int* z;

    SonicXYZ()
    {
        int* p_base = (int*)0x01E11C60;
        int* p1 = (int*)(*p_base + 0x00000010);
        x = (int*)((int)p1 + 0x00000070);
        y = x+1;
        z = y+1;
    }
};

int main()
{
	SonicXYZ sonicpos;
}
Last edited on
I'll try that - but now that I think about it, seeing as how X, Y and Z are all floats, how do I assign the float value of "50" to the X value when it's INT?
Oh, they are floats!

Then we just define the pointer differently.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct SonicXYZ
{
    float* x;
    float* y;
    float* z;

    SonicXYZ()
    {
        int* p_base = (int*)0x01E11C60;
        int* p1 = (int*)(*p_base + 0x00000010);
        x = (float*)((int)p1 + 0x00000070);
        y = x+1;
        z = y+1;
    }
};


Then to assign a value:
1
2
3
4
5
int main()
{
    SonicXYZ sonicpos;
    *sonicpos.x = 50.0f;
}
Last edited on
Those are the exact changes I guessed, and they aren't working. Can you help me determine what might be wrong? I will validate my addresses and offsets. It's most likely my error, being the noob :)

Thanks for your help so much!!
Last edited on
I found the issue. I'm not sure if I'm going to word this correctly.

x = (float*)((int)*p1 + 0x00000070);

An additional dereference operator (*) before the "p1". I'm sorry if my description of the data layout lead to this error.

The code you gave me is AWESOME! Thank you for helping me make my first struct.

P.S. I like how you break it out into seperate lines. I've been bleeding my eyes out with things like the following, which adjusts Sonic's Rings quantity:

*(INT*)((*(INT*)(SonicAddr)) + 0x5b8) = 999;

Last questions:

Since the pointers can change, I need to re-spawn this struct between levels. How do I properly destroy the previous variables? In this case, previous "sonicpos"?

And lastly, I noticed I forgot to initialize the struct I made for saving the current location. The game crashed, with a verbose Visual C++ description of the error. It even knew my variable names. Is this possible because my DLL was compiled in Debug mode? Just curious.
Last edited on
You aren't creating data, just pointers when we create the struct. When the struct goes out of scope, these pointers are automatically deleted. The data will remain, but that's okay, because the data itself isn't yours. You don't want to delete that as it will cause the original program to crash. Therefore you don't need to do any manual cleanup.

If you ever use the "new" keyword, that's when you need to start manually cleaning stuff up. That can be done in the "destructor" like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct A
{
    int* i;

    A()
    {
        i = new int; // the pointer now points to a newly created integer.
    }
    ~A() // This is automatically called with the object becomes out of scope
    {
        delete i; // We have to clean this up or we lose the data.
    }
};


For your stuff, the struct only contains pointers to the position. If you want to save the position, we'll need to something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct SavedPos
{
    float x;
    float y;
    float z;

    Save(SonicXYZ pos)
    {
        x = *pos.x;
        y = *pos.y;
        z = *pos.z;
    }
    Restore(SonicXYZ pos)
    {
        *pos.x = x;
        *pos.y = y;
        *pos.z = z;
    }
}  SaveSlot[10]; // Creating 10 slots to save the position 


Then to save or recall position 0.
1
2
3
4
if (save)
    SomePos[0].Save(sonicpos);
if (restore)
    SomePos[0].Restore(sonicpos);
Last edited on
Thank you, Stewbond!
Topic archived. No new replies allowed.