Since Defense Grid: The Awakening used a, for me, unknown PE Packer, the easiest way to disassemble it is to dump the executable once you have started it. There are various tools out there which allow you to do this, I used LordPE it's easy to use and has a ton of options which I didn't use ;)
The output of this dump is not a working executable. It is possible to create a working executable, but it requires more work which is often not worth the effort. The only reason I could think of would be if you wanted to pre-patch the executable, however this often is only required for cracks.
Anyways, back to the game. We now have a dumped executable which IDA Pro can actually disassemble and with the help of the Hex-Ray's wonderfull decompiler add-on, we where able to convert the function which contained the credit-modification code to semi-readable C/C++ code. While I can read assembly code, its a lot harder and more error prone.
The decompiler has some limitations, for example it can't decompile MMX instructions. If it could, the code would probably be a lot easier to understand. But here's the decompiled function (sub_8BB110)(note that I have circled parts of the function which are of interest):
As you can see, just before the instruction that modifies the credits, _EBX is filled with variable v27, that variable in turn is filled by sub_47E6E0. This might not be clear until you disassemble sub_47E6E0. As you can see in the disassembled code of function sub_8BB110, a pointer was given to v26 but in sub_47E6E0 the result is actually put into v26 and v26 + 4. The last addition actually causes function sub_47E6E0 to write into v26 and v27.
Here's what sub_47E6E0 looks like:
I've added some names to the parameters, one of the parameters "basePointer" is especially interesting. In sub_8BB110 you will see that "basePointer" is v25 + 16. Now the fun part is that if you look back in sub_8BB110 you will see that its filled by v6 + 4. Now its not hard to guess that the same trick done by sub_47E6E0 was done by sub_47E1B0 as well. If you look at sub_47E1B0 you will see a very similar function:
Note that the basePointer for this function is dword_B458E8 + 44.
This however only explains 2 of the 3 parameters to get the pointer to the value we're interested in. The 3rd parameter of function sub_47E1B0 and sub_47E6E0 are actually lookup values. I've called them type values in my disassembly though. These type values originate from a2 (v23 is filled with a2) and a3.
We know that the value that we are looking at is at pointer + 0x10 and if you look at sub_47E6E0 you will see that type-value that it looks for is at 0xC (12). So if we go back to Cheat Engine and decrease the pointer of "credits spent" by 4, we will know the lookup value for the "credit spent". In our case its 9. It wouldnt be hard to find the starting-credit lookup value either, but you can do that yourself ;)
This still leaves the lookup value for sub_47E1B0 (a2), for this we look at the usage of sub_8BB110. If we look at the cross reference of that function and goto the first usage of sub_8BB110, we will see that a2 is filled with dword_B458C4+212. Now I havent fully tested it, but I assume that value always has the right lookup/type value. In testing that turned out to be true anyway.
Now that we have the pointer-lookup scheme of the game, we can write a trainer which uses this information to increase / decrease the credits spent. In part #3 I'll show you how I converted the pointer-code into an external program (trainer) which will increase or decrease the credits spent.