Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Custom type gone wrong

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
oddgamer
Advanced Cheater
Reputation: 0

Joined: 19 Jan 2013
Posts: 60

PostPosted: Sat Aug 16, 2025 9:26 am    Post subject: Custom type gone wrong Reply with quote

So many, many moons ago, I asked the wonderful people here to help me make a custom type for searching for "ticks", to make finding time-related values easier in Rimworld (yes, there are other, easier ways to cheat this game, yes I could turn on the dev mode or edit the save file or any of a billion other things, thank you, I'm aware, I'm having fun doing it this way, moving on).

Time in RimWorld is measured in ticks. 60 ticks to a real-world second (which is shown sometimes), 2500 to an in-game hour, 60,000 to an in-game day (24 in-game hours), and 3,600,000 to an in-game year (60 in-game days), all stored as a 4-byte signed integer. When I want to, say, find the age of someone that is 42 years old, I need to bust out the calculator and figure out what 41 x 3,600,000 and 43 x that are in order to get the possible range of values. Which is frustrating. The idea here would be that the number displayed would be a float or double (probably float) that represents the integer number divided by those various values (so different types for second, hour, day, year).

This one, for finding seconds of time left and from which I adapted the others, does not work. I don't think it ever worked. I didn't write this, I don't know who did (can't find it on here). I gave it a value of 50, which is nearly 60 and so the number reported should be almost 1 (specifically it should be 0.833333). Instead what I get is 1.401298464E-45. Not even close. Can anyone help fix this?

Code:

alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(PreferedAlignment,4)
alloc(UsesFloat,1)
alloc(UsesString,1)
alloc(MaxStringSize,2)
alloc(CallMethod,1)

TypeName:
db 'Tick Seconds',0
ByteSize:
dd 8
PreferedAlignment:
dd 4
UsesFloat:
db 1
UsesString:
db 0
MaxStringSize:
dw #100
CallMethod:
db 1

multiplier:
dd (float)60

//cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
ConvertRoutine:
[64-bit]
movss xmm0,[rcx]
divss xmm0,[multiplier]
movd eax,xmm0
ret
[/64-bit]

//cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
[64-bit]
movd xmm0,ecx
mulss xmm0,[multiplier]
movss [r8],xmm0
ret
[/64-bit]
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4690

PostPosted: Sat Aug 16, 2025 12:37 pm    Post subject: Reply with quote

Quote:
all stored as a 4-byte signed integer

The script is treating it as a float. Convert an integer to/from a float using `cvtsi2ss` / `cvttss2si` respectively

Code:
...

//cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
ConvertRoutine:
[64-bit]
cvtsi2ss xmm0,[rcx]
divss xmm0,[multiplier]
movd eax,xmm0
ret
[/64-bit]

//cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
[64-bit]
movd xmm0,ecx
mulss xmm0,[multiplier]
cvttss2si eax,xmm0
mov [r8],eax
ret
[/64-bit]

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
oddgamer
Advanced Cheater
Reputation: 0

Joined: 19 Jan 2013
Posts: 60

PostPosted: Sat Aug 16, 2025 3:15 pm    Post subject: Reply with quote

ParkourPenguin wrote:

The script is treating it as a float. Convert an integer to/from a float using `cvtsi2ss` / `cvttss2si` respectively


Thank you so much! It's awesome!! Tested and it works!!! This will make life so much easier!!!! I need to stop now, running out of exclamation points!!!!! I may need help!!!!!!

But seriously, thanks for that. I really appreciate it. Smile
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3320

PostPosted: Sun Aug 17, 2025 7:22 am    Post subject: Reply with quote

ParkourPenguin wrote:
...

Isn't there a potential overflow here (due to 32bit register usage)?
Shouldn't 64bit registers be used?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4690

PostPosted: Sun Aug 17, 2025 11:08 am    Post subject: Reply with quote

No. The ConvertRoutine function takes an int (really 4-bytes of arbitrary data), the ConvertBackRoutine function is passed an int, and the native data stored in memory is a 4-byte integer. Everything is 4 bytes.

Setting ByteSize to 8 is weird if the native type is a 4-byte integer (it should be 4), but that won't cause any bad things to happen. CE just gives the functions more data than they need in the input / output parameters. In theory, if the 4-byte value is the last 4 bytes in a scannable region of memory, then it wouldn't be found; however, that's very unlikely to happen.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3320

PostPosted: Sun Aug 17, 2025 2:04 pm    Post subject: Reply with quote

So, multipling two ints can never be longer than an int? That's news to me.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4690

PostPosted: Sun Aug 17, 2025 8:19 pm    Post subject: This post has 1 review(s) Reply with quote

That custom type isn't multiplying two ints. It's multiplying two floats. `mulss` means "multiply scalar single", with "single" referring to floats.

There is a problem with `cvttss2si` (convert / truncate scalar single to signed integer) if the truncated float is outside the valid range of the signed integer output type. This isn't likely to be relevant here: the float we're converting to an integer was created from an integer already in the game. If there was a chance of the float-to-int conversion overflowing, then what happens in the vanilla game when the integer wraps around is far more concerning.

Of course, users could always enter ridiculous values, but if they do that, it's their fault.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3320

PostPosted: Mon Aug 18, 2025 11:47 am    Post subject: Reply with quote

ParkourPenguin wrote:
Of course, users could always enter ridiculous values, but if they do that, it's their fault.

So true
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites