If you want to make a trainer using auto assembler scripts it's quite easy.
Just have a table with a auto assembler script and add it to your trainer. When selecting a auto assembler script your options will be limited to only enable and disable, but you can combine it with other cheats

here is a table and a resulting trainer

infinite balls script:

Code:

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough

Also, if you downloaded Cheat Engine 5.2 before the date this was posted I recommend redownloading it. (fixes a delayed update of the userdefined symbol, and the problem of never deallocating memory in scripts)

You know how to make a trainer with auto assembler scripts, but you want to let your users fill in values for certain stuff. In that case registersymbol is usefull.

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
unregistersymbol(ballsiwant)
dealloc(newmem)
dealloc(ballsiwant)

Pinball.exe+175b7:
mov [esi+00000146],eax

as you see I have created a variable called "ballsiwant" that gets the default value of 3 (in case you forget to update your symbol list, or the trainer has some delay problem, shouldn't be possible though, but just to be safe)

I have created a cheat table with 2 items, the auto assembler script, and the entry with as address "ballsiwant"
now create the table, first add the infinite balls script as a cheat, and IN THE SAME CHEAT , add the "ballsiwant" address, setit to only set a value, and allow user input

give it a hotkey, description etc....
and create the rest of the trainer, e.g usedefined window, images, icons, etc....

when done and you've created the trainer you should be able to use it and fill in how many balls you want to get when you lose a ball. (it is infinite, but you could probably add som code so it only executes it once after setting the balls...)

It is my understanding that nothing ever gets NOP'd because it returns after the NOP. I am led to believe a NOP here wouldn't matter since 3 would replace 3, 2, 1 easily without having to NOP it. I still don't know about NOPPING tho.

Anyways I simplified the code a little, got rid of some labels that helped confused a few things.

Enabled code:

Code:

[ENABLE]
alloc(newmem,2048)
label(returnhere)

Pinball.exe+175b7:
jmp newmema
returnhere:

newmem:
mov eax,3
mov [esi+00000146],eax
jmp returnhere

Disable code:

Code:

[DISABLE]
dealloc(newmem)

Pinball.exe+175b7:
mov [esi+00000146],eax

----------------------------------------------------
Normally when you want to return something you would use the RET command, but you are not suppose to use RET commands in a code cave/allocated memory to my understanding.

Instead we use a returnhere label. What could also be done to my understanding is that you could just JMP to the normal game routine. This means the line directly under the code we are replacing in the disassembler. Given that the code we are replacing is 010175B7 the line under it is 010175BD. so 10175BD is the next normal game routine

Code would look like this:

Code:

[ENABLE]
alloc(newmem,2048)

Pinball.exe+175b7:
jmp newmem

newmem:
mov eax,3
mov [esi+00000146],eax
jmp 10175BD

Pinball.exe+175b7 refers to the address of the opcode, in this case 010175B7

and Finally, Instead of making allocating memory, you could just found a code cave using CE's code cave finder. Make sure the code cave is in the green memory, as others I’ve tried don't work. A code cave I've found was 102E226.

Code:

[ENABLE]

10175b7:
jmp 102E226

102E226:
mov eax,3
mov [esi+00000146],eax
jmp 10175bd

[DISABLE]

10175b7:
mov [esi+00000146],eax

Here is the above code in T-Search form using easywriter:

Patch:

Code:

offset 0x10175b7
jmp 0x102E226

offset 0x102E226
mov eax,0x3
mov [esi+0x146],eax
jmp 0x10175bd

Unpatch:

Code:

offset 0x10175b7
mov [esi+0x146],eax

Disclaimer: I am very new to this and only trying to help out from what I've came to understand. Please understand if any of this information is false and please correct me if I am incorrect.

That nop is required because the instruction(s) being overwritten with the jmp are combined longer than 6 bytes (mov [esi+00000146],eax is 6 bytes, the jmp 5)

if you don't nop the last byte after the jmp, and just jump to there, you will be executing garbage, and a high chance the game crashes, or acts weird

I understand. Are all mov's 6 bytes? or can you explain why this mov is 6 bytes. Also, are all jmp's 5 bytes?

What I get from this post is that before hand the orignal code used 6 bytes, we replaced that with 5 bytes, but there was a byte left over so we NOP it to balanace things.

I see orignally I thought jmp commands were like GOTO statements in the code, and the newmem: was just a way of organizing. I think I understand now that when you have [address]: it writes to that address, much like offset in T-search.

When I saw:

Code:

Pinball.exe+175b7:
jmp newmem
nop
returnhere:

I thought it was JMPing to the newmem part of the code, but it is actually writing a JMP command to the newmem address in the the Pinball.exe+175b7 address (10175B7) and then NOPing.

What is confusing is how returnhere gets the games next routine address simply by just saying returnhere:

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum