View previous topic :: View next topic |
Author |
Message |
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3110
|
Posted: Sun Jul 22, 2012 8:02 pm Post subject: Need help: Create new custom data type |
|
|
Hi all,
I don't know the first thing about creating a custom data type, so I am seeking help.
The value consists of 5 doubles, like this (stored in the memory in this order as well):
Code: | double dVal;
double dKey1;
double dKey2;
double dChecksum; // Irrelevant
double dZero; // 0 or 1; 0: valid, 1:invalid
| The real value is a combination of three doubles follows:
Code: | dSearchVal = dKey1 - dKey2 + dValue; |
I guess it would speed up the code if there was a check that dZero is actually 0.0d before doing the math. Just a thought.
Thanks for any tips!
A complete solution would be even better
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25296 Location: The netherlands
|
Posted: Mon Jul 23, 2012 5:59 am Post subject: |
|
|
I'm not good with fpu asm, but one method is to use an extra dll, here's the framework for that
Code: |
[64-bit]
LOADLIBRARY(mytype64.dll)
[/64-bit]
[32-bit]
LOADLIBRARY(mytype32.dll)
[/32-bit]
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,1)
TypeName:
db 'Custom Type Name',0
ByteSize:
dd 28
UsesFloat:
db 1 //Change to 1 if this custom type should be treated as a float
//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: stdcall float ConvertRoutine(unsigned char *input);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
jmp mydllfunctionconvertroutine
//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: stdcall void ConvertBackRoutine(float i, unsigned char *output);
ConvertBackRoutine:
jmp mydllfunctionconvertbackroutine
|
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Jul 24, 2012 4:43 am Post subject: Re: Need help: Create new custom data type |
|
|
@Csimbi
I made something similar, for structure with floats. I think I can adapt it to doubles.
Stay tuned (approx. few hours).
Edit:
here:
Code: | alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,4)
alloc(PreferedAlignment,4)
alloc(ConvertRoutine,1024)
label(SKIP)
TypeName:
db 'CustomType_for_Csimbi',0
ByteSize:
dd (int)40 // struct has 40 bytes
UsesFloat:
db 01
PreferedAlignment:
db 04
//double dValue; //0x00
//double dKey1; //0x08
//double dKey2; //0x10
//double dChecksum; // Irrelevant //0x18
//double dZero; // 0 or 1; 0: valid, 1:invalid //0x20
//dSearchVal = dKey1 - dKey2 + dValue;
define(dValue ,eax+00)
define(dKey1 ,eax+08)
define(dKey2 ,eax+10)
define(dZero_1,eax+20)
define(dZero_2,eax+24)
ConvertRoutine:
push ebp
mov ebp,esp
mov eax,[ebp+8] //place the address that contains the bytes into eax
cmp dword ptr [dZero_1],0
jne SKIP
cmp dword ptr [dZero_2],0
jne SKIP
finit
push eax
fld qword ptr [dKey1]
fadd qword ptr [dValue]
fsub qword ptr [dKey2]
fstp dword ptr [esp] // store and convert to float
pop eax
//(I used qword three times because values are "double". I used dword at the end because UsesFloat is used)
pop ebp
ret 4
SKIP:
mov eax,7fffffff // gives NaN, CE will skip it
pop ebp
ret 4 |
I tested it with this
Code: | [ENABLE]
globalalloc(testing,2048)
testing:
dq (double)123.0
dq (double)50.0
dq (double)40.0
dq (double)44
dq (double)1.0
dq (double)123.0
dq (double)50.0
dq (double)40.0
dq (double)44
dq (double)0.0
[DISABLE]
dealloc(testing) |
Searching for value 133.0
results:
It finds second structure at "testing+28",
structure at "testing+00" is skipped.
_________________
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Jul 24, 2012 5:31 pm Post subject: |
|
|
@DB
OK, I found small problem. NaN's + Inf aren't filtered out. Above customtype script will work for "exact value" scans.
(decreased, increased,... scans are problematic).
Because you used (in memscan.pas):
(...)
vtCustom:
begin
//dword config
FoundBufferSize:=buffersize*customtype.bytesize;
StoreResultRoutine:=GenericSaveResult;
if customType.scriptUsesFloat then
begin
case scanOption of
(...)
GenericSaveResult doesn't filter NaN's Inf for customType "scriptUsesFloat := true".
So, I suggest
(...)
vtCustom:
begin
//dword config
FoundBufferSize:=buffersize*customtype.bytesize;
StoreResultRoutine:=GenericSaveResult;
if customType.scriptUsesFloat then
begin
StoreResultRoutine:=CustomScriptUsesFloatSaveResult;
case scanOption of
(...)
new function CustomScriptUsesFloaSaveResult with isnan and IsInfinite checks.
_________________
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25296 Location: The netherlands
|
Posted: Tue Jul 24, 2012 5:49 pm Post subject: |
|
|
Ok, i'll check that.
Also if instead of NaN you make it return 0 it won't be such a big problem. (Increased/decreased on a value that stays 0 will get filtered out. Just don't scan for the value 0, but who would do that anyhow?)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Tue Jul 24, 2012 6:08 pm Post subject: |
|
|
OK. I've changed mov eax,7fffffff to
mov eax,0
Problem still occurs.
And what if you want to find few structures at once?
real values (combination of three)
1) scan type: "unknown initial value", value type: "CustomType_for_Csimbi"
2) do something in game, the real (combination of three doubles) values increase
3) next scan, increased value
Many +Inf , 0 and ??? in found list.
Edit:
btw. "increased value by" 1.0 gives many NaN, -Inf, +Inf, 0 and ??? as well.
mov eax,7fffffff and mov eax,0 gives almost the same thing.
Edit2:
This does the trick
Quote: | Index: C:/ce62/memscan.pas
===================================================================
--- C:/ce62/memscan.pas (wersja 1480)
+++ C:/ce62/memscan.pas (kopia robocza)
@@ -2427,7 +2427,13 @@
{
Generic routine for storing results. Use as last resort. E.g custom scans
}
+var f: single;
begin
+ if ((variableType = vtCustom) and customType.scriptUsesFloat) then
+ begin
+ f:=customType.ConvertDataToFloat(oldvalue);
+ if (isnan(f) or IsInfinite(f)) then exit;
+ end;
//save varsize
PPtrUintArray(CurrentAddressBuffer)[found]:=address;
copyMemory(pointer(ptruint(CurrentFoundBuffer)+ptruint(variablesize*found)),oldvalue,variablesize); |
_________________
|
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3110
|
Posted: Tue Jul 24, 2012 9:33 pm Post subject: |
|
|
Hi there,
I took the script mgr.inz.Player posted and put it into CE.
I started a scan (exact value) and I got this error (see attachment).
Any thoughts?
Can it be that the code "reads over" into unallocated/inaccessible memory?
Description: |
|
Filesize: |
6.53 KB |
Viewed: |
30813 Time(s) |
|
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Wed Jul 25, 2012 2:38 am Post subject: |
|
|
@Csimbi
try it again, under cheatengine-i386.exe
edit:
If you want to filter out NaN and +-Inf ......
Rev: r1481
Commit log message: custom type (float) improvement
Date: Today (2 hours ago)
Author: cheatengine
http://dl.dropbox.com/u/63264075/r1481_cheatengine-i386.7z
_________________
|
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3110
|
Posted: Wed Jul 25, 2012 4:18 pm Post subject: |
|
|
Wow, it works (with the new build you provided)!
Thank you very much!
I am happy to confirm that the "found out what instructions access this value" work, too.
When I try to change the value in the table, I get an error saying that "the value 'x' could not be parsed". They value can't be frozen in the table, neither - probably for the same reason.
Is there a way to tell CE how to write the value (not just read it) directly in the table (not via AA or LUA scripts)?
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Wed Jul 25, 2012 4:50 pm Post subject: |
|
|
Because there is "ConvertRoutine" only.
You need "ConvertBackRoutine" as well.
Edit:
Add this at the end
Code: |
ConvertBackRoutine:
push ebp
mov ebp,esp
push eax
push ebx
// [ebp+8] //value
// [ebp+c] //destination address
fld dword ptr [ebp+08]
mov eax,[ebp+0c]
fadd qword ptr [dKey2]
fsub qword ptr [dKey1]
fstp qword ptr [dValue]
pop ebx
pop eax
pop ebp
ret 8 |
and alloc(ConvertBackRoutine,1024) at the beginning.
_________________
Last edited by mgr.inz.Player on Thu Aug 02, 2012 2:00 am; edited 3 times in total |
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3110
|
Posted: Wed Jul 25, 2012 5:05 pm Post subject: |
|
|
Should be:
dVal=User-entered-value;
dKey1=any;
dKey2=dKey1;
dChecksum=any;
dZero=0;
So, I imagine it's something like this:
Code: |
ConvertBackRoutine:
fld qword ptr [eax]
fst dword ptr [dVal]
fst qword ptr [dKey1]
fstp qword ptr [dKey2]
ret
|
?
Edit
Added the code pieces as you said.
It's just wonderful. Works almost perfectly.
The only glitch is the case of very large numbers (see attachment).
Somehow these show up weird. It this a CE bug?
Description: |
|
Filesize: |
7.25 KB |
Viewed: |
30671 Time(s) |
|
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Thu Jul 26, 2012 3:16 am Post subject: |
|
|
You can request a "UsesDouble", ask DB
I can make this, no problem for me, only copy paste + few modifications.
_________________
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25296 Location: The netherlands
|
Posted: Thu Jul 26, 2012 7:10 am Post subject: |
|
|
It's not because it's a double or float
This is a parsing problem (no value should begin with a 0)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Thu Jul 26, 2012 1:06 pm Post subject: |
|
|
I've just added "usesdouble".
Code: | alloc(UsesDouble,4)
UsesDouble:
db 01 |
Changes:
http://paste2.org/p/2083785 (mirror)
http://paste2.org/p/2083883 (DefineNewCustomType) (mirror)
Binary file cheatengine-i386 + txt file with convert routine scripts:
https://dl.dropbox.com/u/63264075/r1481_%2B%2BusesDouble_cheatengine-i386.7z
Of course, it breaks backward compatibility.
For old ConvertRoutine scripts, it's better to add xor edx,edx at the beginning.
For old ConvertBackRoutine scripts, we have to change [ebp+c] to [ebp+10], and "ret 8" to "ret c"
##############
##############
For 32bit (didn't tested 64bit)
- ConvertRoutine - output registers: eax and edx
Ex.
ConvertRoutine:
push ebp
mov ebp,esp
xor edx,edx
(...)
//storing double value
sub esp,8
fstp qword ptr [esp]
pop eax
pop edx
// for example: eax=00000000 and edx=402E0000 gives 15.0 double
pop ebp
ret 4
(...)
- ConvertBackRoutine, now it is like this:
[ebp+8] contains dword(integer, single) or qword(8byte, double)
[ebp+10] - keeps address of destination
##############
##############
And I can use 999999999999999 custom value. With key1 = 50 and key2 = 40,
dValue is 999999999999989.
So without parsing problems.[/url]
_________________
Last edited by mgr.inz.Player on Fri Jul 27, 2012 6:05 am; edited 2 times in total |
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3110
|
Posted: Thu Jul 26, 2012 6:54 pm Post subject: |
|
|
Works perfectly (both the data type and the newly compiled binary).
I'll check with 64bit version once a new build is available.
Well, what can I say? Hats off!
Do you think DB will adopt it in the next release?
One question regarding the old and the new type definition.
In the old one, there was a 'push eax' after finit and before the float artithmetics, as well as a 'pop eax' after the value has been stored.
In the new one, the initial 'push eax' is gone.
I do not understand why. Could you explain?
Thank you.
|
|
Back to top |
|
|
|