English Amiga Board

English Amiga Board (http://eab.abime.net/index.php)
-   request.UAE Wishlist (http://eab.abime.net/forumdisplay.php?f=56)
-   -   WinUAE - Trainer Plugin (http://eab.abime.net/showthread.php?t=95606)

Toni Wilen 29 December 2018 10:29

Stupid and pointless posts ("I know I am right, you are wrong") end here or there will be trouble.

Hint: I actually want to implement this feature (for years, searching is always useful) but it needs to be perfect. There are far too many stupid trainers that for example break the game later and some of them are really only needed in specific places and not all the time. In game keys are not that common.

BippyM 29 December 2018 10:37

Toni. I agree and I think you're right about the digital signature. I am familiar with using ar3 and the fa opcode so if you were to implement something similar I could test it and iron out any issues and bugs.

Maybe have a seperate tab or another window open whilst training the game. This could show the memory one is looking at whilst training.

A unique md5 could possibly be created of the setup used (this way installed games could be trained) as using a different rom, HD image etc could cause issues.

Alternatively limit it to disk images only initially, but again games like dune2 on 6 disks would he a pain.

tlenl 29 December 2018 11:01

As i've undestood, the point of Toni is to find in realtime (as the game running) the "Functions" (or single function) that modify the "searched" value, and when found (always in realtime) to modify them on the fly to make them do what we want to do (freeze the value, modify the value, do nothing).

This methodology if well implemented would work on ANY version of the game, disk, whd, dos and even already cracked and trained versions pheraps.

BippyM 29 December 2018 12:04

Already trained won't necessarily work due to the fact the trainer would possibly modify the code.. for example the code that would subtract one from a life would most likely be nop'd out, making the signature different

Toni Wilen 29 December 2018 12:14

All the "trainer helper" utilities will be in debugger, GUI will only have trainer selector (and that will have the lowest priority anyway). There is no way to make "good" trainer without basic knowledge of m68k assembler. Debugger already has many helper options like fa from AR3.

Main goal is to have single trainer that automatically works with all different "variants" of same game version: copy protected original, most cracks, whdload, custom hd installer(s), etc.

Different original release versions (or leaked betas) of game most likely required slightly modified "patch" code.

Hash won't really help because all the absolute addresses still need filtering so some kind of "skip array" is still needed and I also don't want to allow anyone to "obfuscate" how the trainer works (at least without more deeper knowledge)... Matching is also much faster when using "plain text".

tlenl 29 December 2018 12:43

The signature of the function, would not be the hash of the function itself but rather,
or its name (i'm a little rusted on assembly but if i remember correctly the function name is at least partially preserved in the compiled code)
or (little bit more complex but pheraps more resilient) its "position" in offset terms to other functions surrounding it.
Fingerprint: -2,-30,-70,15
or more efficiently from lowest to higher 15,-2,-30,-70
Means that summing each of this value to each address of function allocated in memory would result in an unique (identical) address wich corresponds to another function (our function).
In the example we would sum 4 values to 4 functions (if there are 5 functions).
It there are more functions allocated we would permutate the associations of value to sum.
With a total of 16 allocated functions we would have 4 offset to apply to 4 functions in rotation till find a same address on 4 different sums (wich necessary has to be the one).
More offsets gives more precision.

I'll have to verify all of this (the assumption is that a set of functions is always relocated with the same offset).

BippyM 29 December 2018 14:49

I have no idea what you are trying to explain!

tlenl 29 December 2018 15:52

Eheh i'll try to explain later if it will have some use (or sense!) in what we need!

For the moment using a mix of AR3 and WinUAE debugger
this is the function (??) decrementing lives in gods


000039EE 5378 0224                SUB.W #$01,$0224 [0002]
000039F2 6a00 feca                BPL.W #$feca == $000038be (T)
000039F6 4eb9 0001 2daa          JSR $00012daa
000039FC 3f00                    MOVE.W D0,-(A7) [0010]
000039FE 3f01                    MOVE.W D1,-(A7) [0010]
00003A00 323c 0064                MOVE.W #$0064,D1
00003A04 303c 002a                MOVE.W #$002a,D0
00003A08 4eb9 0001 faf2          JSR $0001faf2
00003A0E 321f                    MOVE.W (A7)+ [2004],D1
00003A10 301f                    MOVE.W (A7)+ [2004],D0

I think i'll definitely have to polish some ASM 68000 manual :D

@Toni Wilen
The 68000 architecture has a kind of stack in wich are memorized all of the addresses of the functions loaded in memory?

If yes there is a way i can query the debugger to show me the list?

(Or there a no function at all in asm?? Damn what an ignorant.... learn...learn...learn)

Forgive me for my poor assembly preparation :(

Toni Wilen 29 December 2018 16:15

Using your Gods example to generate "fingerprint":

JSR $000012daa has absolute address so one possible "fingerprint" would be:

5378 xxxx 6a00 feca 4eb9 xxxx xxxx 3f00 3f01 323c 0064 303c 002a 4eb9

Where xxxx = ignore because it contains absolute address that can change (if it would have been dos loaded). I am not sure if this is long enough to guarantee no other code gets matched but it probably is unique enough. Trainer system can relatively easily autodetect if there are multiple matches.

When UAE detects that this first instruction in above string is about to get executed, it would check type of patch: a) skip the instruction b) store the destination of sub in internal variables and mark it as frozen c) set it to some static value (like 99).


The 68000 architecture has a kind of stack in wich are memorized all of the addresses of the functions loaded in memory?
No. Hardware does not anything like this. AmigaOS keeps this info but it should not be used to keep this system generic.

tlenl 29 December 2018 17:28

WTF Toni, after reading a quick ASM tutorial (NEO: "I know kung fu.") i've understood everything you're talking about! :D

You include in your fingerprint everything is absolute and fixed (D and A registry and constants #) and mask everything variable (memory addresses).

In your case the first number 5378 identify the SUB to patch.

We could extend the concept making a variable FINGERPRINT and an offset identifying the number position to patch in case of particularly difficult code block to make unique. Like:


So in gods case


If for example we would have to go "before the instruction" we would have


and so


What do you think about?


Back to square one, the offset would identify the VARIABLE to patch not the FUNCTION

so it would be written in the plugin






Toni Wilen 29 December 2018 19:19

Exactly, something like that, offset to opcode word (usually offset to opcode itself is fine because most instructions don't do both read and write from different addresses) that points to the variable.

Length of whole string is not needed, it can be calculated automatically.

Then some metadata is also needed: name of patch/cheat, if enabled or disabled by default (so that user can set the default easily), default "in game" key (if needed). Type of cheat ("nop", "freeze", "set", "set+freeze"?). If "set value" type cheat, default value to be set.

Each patch/cheat needs at least 1 fingerprint string but more than one should be allowed.

I plan to make above default options adjustable in GUI.

tlenl 29 December 2018 19:24

Yes and returning to some posts above, a method of listening to events (wich translate to listening to fingerprint) to happen before trigger the patch.

The entire plugin architecture could be transformed in XML wich would contain GUI elements, their type, their state and the associated fingerprint to apply (or not).

Toni Wilen 29 December 2018 19:31

I am most likely going to use "ini"-like format because custom portable ini reader/writer is already included, it is used to read and write "portable" mode winuae.ini.

I am not going to add XML parser libraries only for parsing trainer files..

tlenl 29 December 2018 20:01

I agree.

Can you modify the next release of the debugger to add to the

d command

and option to specify the offset in order to show lines "before" the address?

it would be easier to analyse problematic groups.


d <address> [<lines>]

could be

d <address> [<offset>] [<lines>]

like showing 10 lines before address

d <address> -10 20

it shows 20 lines from -10 to +10

Toni Wilen 29 December 2018 21:27

d <address>-x already works (subtracts x from address, note: no white space allowed). Going backwards by line count is not reliable because instruction length is variable and it is not possible to know if it is code or only data that looks like code.

tlenl 30 December 2018 08:28

Very good.

I would add to the functions the offset parameters (starting from left to right) with the word width (byte,word,long).
This because same parsimonius game could use a word to memoryze two small counters (each 2 bytes) and we would lock only the second group.

STARTLISTEN([b,w,l]<OFFSET>,<FINGERPRINT>,<frequency>,<hook function>)

Moreover i would add debug functions like


In case of Gods


work ok


works ok too because the live number is on the second byte

If the game would memoryze two different values in the word we would have (for example)

We would like to write a long word (like adding 8 milions to money eheh)

We would have (if FINGERPRINT points to a long)

or in the middle of the long for whatever reason


Toni Wilen 30 December 2018 15:52

It would be too extreme special case if datatype size needs overriding..

Lets get basics working first. First I need to find good enough implementation for fingerprint matching that is reliable and won't take too much CPU power.

Debug options should not be needed because I'll add lots of logging for debugging purposes anyway and most of it can be left active because it can't cause any log flood.

Toni Wilen 31 December 2018 21:40

Minimal support now done (usual winuae.7z link):

Config file entry: trainerfile=<path to ini file>

Ini file format (extremely basic for now):

data=200e46802d400026200c6602 ; this is a comment

EDIT: xx mask values are also supported.

This triggers early in boot phase when starting KS 1.3 config. (00FC0282 2d40 0026 MOVE.L D0,(A6,$0026))

data="fingerprint" data
offset=offset to instruction that modifies required variable (2 = 2 words = 2d40 in above example). Not required, default zero.
eaoffset=offset from instruction to instruction's source or destination effective address word(s). Only needed if instruction is MOVE with both source and destination pointing to memory. Not required, default zero.

More will be added later..

Message is logged when match is detected. Instruction address, variable address, size and current value is included.

No trainer options yet.

"More compatible" CPU option must be set.

tlenl 02 January 2019 08:39

Hi Toni, happy new year.

Wouldn't be better to look for (and operate) on the variabile rather than on the function?

The variable once found is (quite for sure) static in the game.

Looking for function is not garanteed to be effectively in all the situations.
Could be for example that different functions would modifies the variable in different place (on different situations in the game).
In this case we would need to find "all the different situations functions" instead of just finding the variable once.
(Once found the variable who cares what function modify it).

Moreover when "finding" the variable to lock, the person could find the right variabile, but it would be possible to mask the "wrong" memory block (if for example is better for uniqueness).

The only requirement would be that the result of the mask is the right address.

Offsetting the wrong function would make the patch not working.

Moreover masking the variable (and operating on it more than on the functions that modifies it), would make the patch more generic and resilient and pheraps could work on cracked and trained too.

We could find the right memory block, the right variable, but mask out the already trained "NOP" function, or just select another memory block wich address the variable and that is untouched accross the original and trained versions.

But in the end the advantage for the person finding the trainer is that it just need to find the variable in memory (and so mask it in whatever place the variable is operated) instead of finding the exact place and function where the function operating the variable is.

I remember your initial requirement was to find a way to identify the variable address in a dynamic way (not with absolute address).

Toni Wilen 02 January 2019 19:02

As I have said, you can't reliably find the variable without first finding code that reads/write it and even if you find some way to directly search for the variable address (find data bytes "abcsdsdkj", add 17823 to its address to find the variable), it would be too difficult to use and it is impossible to know if it actually works in any other variant without testing. It is very difficult and time consuming to find out if data is static or it changes in some situation.

My method can be used (more or less) if you know basics of m68k assembly and it is quite reliable. Long (20+ bytes) code sequence is usually unique enough. Can't also misdetect code from some random temp buffer because it will be only detected if it is getting executed. This is very possible when only looking for data bytes.

If you don't like it that "watched" variable needs to be changed before address is found:

Find out code which is used to READ the variable (for example to show the life counter value on screen), it can be found immediately at game (level) startup. Job done, address is now known and it usually stays the same as long as game is running.

"fa" command should usually find all locations easily enough. This is why I prefer this method, it is simple: find the variable (using trainer options in debugger/ar3), then simply use "fa" and the rest is simple disassembly to check code around the read/write instruction. Of course there are situations when finding the variable requires much more m68k experience but I still don't want to make this too difficult when it does not need to be difficult.

All times are GMT +2. The time now is 05:24.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.

Page generated in 0.06223 seconds with 11 queries