|
#1
|
|||
|
|||
|
Starting with a basic trainer, and evolving/expanding the project in time once I discover more. I'll keep a diary of what I did, so others benefit from this experience. Also, adding some stuff I discovered while analyzing the game or its files. Hope this board allows constant editing of same post (I'd hate to double/triple post)
First off, let me say that I've tested all the trainers available for this game and all of them have only one option available (Unlimited ammo), and even so, that option is global (works for both player and enemy). Well, if they also had god mode, it wouldn't have been a pain in the ass to have enemies with Uzis shooting constantly on your ass ![]() Therefore, I've been trying to conceive an ammo feature for the last few hours, and since I couldn't find a base pointer for my player (it shifts like mad, even though the game doesn't use code-shifting), I decided to call in for ingenuity and use another method :X Kinda g4y, but it works pretty nice. Let me show you what I'm talking about... [ Diary log #1 ] Both the enemy and I are using the same function, located here : ![]() That's the code that would normally appear amongst others in your debugger window, when you're trying to see what writes to your ammo address. Quote:
We want it one sided, and for that, also taking into account that I wasn't able to find a base pointer for the weapon pointer, I used something else. Noticed this : ![]() Interesting - "enemy" - that word appears whenever the enemy uses that sub. Problem is the syntax is not always in the same manner. For instance, the pistol will always be "Enemy-pistol-ammo-..." while testing for Uzi, I saw "UZI-ammo-enemy-..." In case you don't follow so far, I'll use word comparing So far - I'm at level 3, where you have to gain access in a cathedral by blowing its walls, right after Doctor Wolf flies out in a chopper - I haven't encountered a weapon to have the letter y in its description, therefore, the script - I hope you have Cheat Engine 5.3 installed !Quote:
--- [ENABLE]/[DISABLE] This is common CE syntax, pretty much and quite similar to ON/OFF. What's below the [ENABLE] tag will work as enabling the cheat/turning on the feature. The script will perform, once assigned to your cheat table, what ever is written below the [ENABLE] tag. How far ? Till the [DISABLE] tag. Same thing goes for [DISABLE]. What ever's under it will be written once you deactivate the script (tick/untick in your table). [DISABLE] works as "restore all" feature, except it restores only what you assign under it. --- alloc(cave,256) CE allows users to allocate memory of different sizes, which is pretty easy to work with, removing the worry to have to find an empty cave to write your code in. The syntax is as follows : alloc(name,size) --- label(back) label(loop) label(out) label(enemy) The use of labels is also possible. Using labels you can set "waypoints" in your code to work faster and easier. Syntax : label(name) - note that numbers aren't supported in any name. --- dealloc(cave) The memory you allocate can be easily deallocated. It's also useful to use this code at the end of your script, since the allocated address will always be the same. If you don't use it, CE will keep allocating different addresses to your cave. --- [DISABLE] 5CC158: sub [eax+538],ecx dealloc(cave) This is the original code, and that's what CE will write when I disable the option. It's the equivalent for a "turn off the cheat" option. --- Now to the main "plot" : cave: pushad loop: mov bl, [eax+14] cmp bl, 79 je enemy cmp bl, 0 je out inc eax jmp loop out: popad jmp back enemy: popad sub [eax+538],ecx jmp back 5CC158: jmp cave nop back: What will the code do is to copy the string I mentioned earlier (Enemy-pistol-ammo-standard-8237) letter by letter and move it in a register, then compare it against the letter y. If that letter is encountered when scanning the string, perform normal code. If not, skip the sub [eax+538],ecx instruction. If the sub is skipped, we don't get anything deducted from out ammo, therefore one-sided unlimited ammo... --- cave: That is the address I've allocated at the beginning. The syntax for writing to it is : name: Basically, you tell CE to write at address "name", in my case at address "cave" ![]() --- pushad Saving the state of the registers, since we'll perform operations and use them. It's always nice to save the state, as the game might crash if one of the registers you use is overwritten. --- loop: This is the first label I declared. Labels can be used as addresses, or part of a code. In this case, "loop" will be an address located immediately below the "pushad". You'll see how the full code looks like in the end. --- mov bl, [eax+14] cmp bl, 79 je enemy I chose to work with ebx, and since I'm operating with letters (bytes), I'll use the lower part of ebx (32b), which is bx (16b) and can be sparsed in 2 (bl, bh - both on 8b). 'l' for lower, 'h' for higher. The text string you saw in the 2nd picture is located at eax+14. The pointer is eax, eax+14 is the address holding the string. So - move in bl the first byte found at address eax+14 -> mov bl, [eax+14]. Further on, on the 2nd line, we compare bl with 79 (letter "y" in hexa). If they match (if y is found within the string), jump to label "enemy", where the game will allow their ammo to decrease ![]() --- cmp bl, 0 je out inc eax jmp loop If bl is not 79, compare it against 0. In case you haven't noticed, we only need to compare the string and stop after it. Or we'll hit an endless loop, and game will freeze. So, the cmp I added will check if the whole string has been "scanned" and stop at first 0 that's encountered. If bl is 0, jump to label "out", where the game executes a code that misses the "sub", therefore we don't get any ammo deducted. If bl is not 0, increase our pointer to move on to the next spot, and return to label "loop" to go through the function again, till the whole string is read. --- out: popad jmp back enemy: popad sub [eax+538],ecx jmp back Label "out" defines another address in the cave, at which we land from the jump mentioned above. We use "popad" to restore the state of the registers and allow the game to get back in "flow" Once the code is used, we jump back to address "back" (you'll see below)The other label does the same thing, except it does it for the case in which the letter "y" is found in the string. --- 5CC158: jmp cave nop back: Our original address 5CC158: at which we write what's below it. The original code has 6 bytes (count them in the 2nd pic). A jmp uses only 5 bytes, so we'll use a nop to even out the code. 5+1=6. As I said above, once the out/enemy labels are used, at the end of each other you see "jmp back". Well, if you look at the code, I used in the function "back:" which defines an address located below the "nop". Therefore, "jmp back" means - jump to the address located below that nop. Since the sub had 6 bytes, "jmp back" means jump to 5CC158+6. Hope it's clear... --- Phew. Long article. Once you copy the script, open up Memory View, press Ctrl+A and paste it the auto-assembler window. From the top menu (in that window), choose "Assign to table". Then check you table. You'll see what I meant with ON/OFF Ticking the checkbox in front of the script means ON/ENABLE. Unticking it equals OFF/DISABLE.Time to show you how it all looks like : ![]() Hope now it's understood. Last edited by کunβeam; 15-04-2007 at 20:15. |
| Sponsored Links |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Rainbow Six Vegas v1.04 Trainer Doesn't work | mfw41 | Game Trainers | 7 | 30-03-2007 22:13 |
| The best (and fun) NFS:Carbon trainer available | intoksicated | General Gaming | 3 | 22-12-2006 04:55 |
| Gothic 2 Trainer prb | Dark3lement | General Gaming | 3 | 17-08-2006 15:50 |