sannybuilder / dev

Sanny Builder Bug Tracker and Roadmap development
https://sannybuilder.com
49 stars 0 forks source link

GTA3 floating point math increments at 0.0625 at a time #221

Closed KyonkoYuuki closed 1 year ago

KyonkoYuuki commented 1 year ago

This is a really weird issue. I was debugging why some code wasn't working and made this simple counter CLEO script

{$CLEO .cs}
0@ = 0.0
while true
    wait 500
    0@ += 0.1
    0AD1: show_formatted_text_highpriority "%.6f" time 500 0@
end

One would expect it to go up like [0.1, 0.2, 0.3, 0.4, 0.5]

But instead, it goes up like [0.0625, 0.1250, 0.1875, 0.25, 0.3125]

Adding different values like between 0.0-0.6 causes 0@ to not change, while adding something like 0.2 causes it to go more like [0.1875, 0.3125, 0.5625], as if it was rounding to the nearest floating point divisible by 0.625. I'm not sure if this is a Sanny Builder thing or GTA3 thing, but it does work as expected for VC and SA.

Setting values like 0@ = 0.3 does the same thing as well, where this rounds down to 0.25

KyonkoYuuki commented 1 year ago

I tried to decompile the .cs file and sure enough, its different

// This file was decompiled using SCM.ini published on 2021-05-25
{$CLEO .cs}

0@ = 0.0 // @ = float 

:NONAME_8
wait 500 
0@ += 0.0625 // @ += float 
print_formatted_now "%.6F" time 500 0@ 
jump @NONAME_8 
x87 commented 1 year ago

This is how floats work in GTA III. https://gtamods.com/wiki/Talk:Mission_Scripting_(Overview)#Fixed-point_remark

KyonkoYuuki commented 1 year ago

Interesting, I'll have to figure out other ways around that then. Thanks!

x87 commented 1 year ago

This limitation only affects floating-point literals. You can't use 0@ = 0.3 because the compiler truncates the value to 0.25. But you can bypass it by writing an IIIE-754 representation of the float into a variable (they are 32-bit and contain values as is).

0@ = 0x3e99999a // see https://www.h-schmidt.net/FloatConverter/IEEE754.html
print_formatted_now "%.6F" time 500 0@ 

let me know if that works.

KyonkoYuuki commented 1 year ago

Yes, that works. Interesting too because it can do floating point math fine. I just had to adapt it to look like this and it works fine

{$CLEO .cs}
0@ = 0x3e99999a  // 0.3
while true
    wait 500     
    000B: 0@ += 0x3c23d70a  // 0.01
    0AD1: show_formatted_text_highpriority "%.6f" time 500 0@
end