I planned to write this blog a few days ago, but my main PC (the one I hack on) decided to die on me and couldnt get it fixed until late last night. But its up and running and I finally got around to finishing my trainer for Trine.
As mentioned in my previous blog, turning on "Unlimited Health" made enemies invincible too. That ruins the playability of the game a bit. So one of the first things you check is to see if the function that decreases health is used on a different spot for players then for enemies. This wasn't the case, my guess is that the players are part of the same entity-array as the enemies.
Since we couldn't use that as a base-reference, I did a quick search (using Cheat Engine) for a static address for the player-structure. Perhaps its in there somewhere, but I got bored of looking for it ;)
So whats left? Well figure out how the game "knows" its a player instead of an enemy. I wont post the entire decompiled function (it has 1300 lines!) but you can download it by clicking here.
If you download the function, then you'll see that at line 1254 the new health is calculated. Whats interesting is the part where it would decrease the damage by certain collectible items. It starts at line 1186 and ends at 1249. Now I didnt really care to figure out what it did there, but the if at line 1186 was interesting.
This "if ( (a2->byte212 && a2->dword1D4 || a2->dword1CC) && a2->dword960 != 1 )" basically checks if the current entity is the player or an enemy, as enemies don't have items. Some further analysis (using pointers found with Cheat Engine) reveals that pointer + 960h = 2 for a player while its 1 for enemies.
Now we have a way to check if the type of entity (who's health is being decreased). Now we have to modify the instruction at 691BB2h to only decrease health for enemies. However we can't magically add instructions to an executable, so we have to allocate some memory (or use a codecave, but thats something for another day) in Trine, write the instructions in there that we want to "add" and then redirect the program flow to this newly created piece of code.
First we have to write some assembler which we can write to the allocated piece of memory, I chose for this:
cmp dword ptr [ebx+960], 2 // Check if its a player
je 691BB8 // Yes, jump back
mov [ebx+254], esi // No, decrease health
jmp 691BB8 // Jump back
What we basically do is check if its a player, if it is we jump back to the original function, if its not we decrease health and jump back. We have to decrease the health, because thats the function we are replacing. You could possibly change "mov [ebx+254], esi " into "mov [ebx+254], 0" which would instantly kill everything when you hit it.
After we created this code inside our newly allocated memory, its just a matter of replacing the instruction at 691BB2h with a jump to our piece of code and voilla. Players stay alive and enemies die.
I made a small trainer which you can download here. It includes a modified "Unlimited Energy" as nop'ing that function didn't always have the desired effect. My new modification is to always write the maximum energy into the current-energy field.