News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Unpacking fixed point floating value

Started by BytePtr, May 02, 2015, 09:02:12 PM

Previous topic - Next topic

BytePtr

Hi.
I have values like these:
Fix16 x,y,z;
Fix16 radius;


Here is the description what is Fix16. Basically its a SIGNED SHORT value: –32,768 to 32,767
Info from the docs: (x,y,z) is the position of the light in (1.8.7) fixed point world co-ordinates . The upper 9 bits of each number stores the block across the map ( with a sign ), and the lower 7 bits stores the position within the block.
radius is the radius of the light in blocks, again in (1.8.7) fixed point. The maximum is 8. Fractions are allowed.


Here are example values:
X: 5
Y: 6
Z: 3

XYZ also could have offset 0..127 (byte?), but lets say offset is all 0 at the moment.

Radius example value has format like A, BBB, so for example:
A, BBB
4, 115

A value can be up to the 7. Minimum 0.
BBB values can be up to the 127 again. Minimum 0.

The "packed" value for these example values are as following:
X: 640
Y: 768
Z: 384

Radius: 627


So far i have found that one must use this piece to unpack XYZ to get actual "unpacked" X,Y,Z values:
Example for X value:

mov ax, 640
and eax, 0ffa0
movzx eax, ax
shr eax, 7


And in eax will be value 5 after this.
Have to do same for Y,Z also and i will get: 6 and 3 accordingly.

What about the offsets? How to get them?
What about radius fractions?
I can get radius A value fine with it. But not the fractions.

Im unable to get the XYZ offset and radius fractions.

Can somebody point me in right direction?
Should i use some binary calculator to figure out how signed word is represented?
And mask the bits off i need or do not need?

TIA.





dedndave


BytePtr

It is, but thats the all of the information about it in this doc.

Its from game map. And and map format specs describe this.
http://www.gouranga.com/files/utils/gta2/gta2formats.zip

Map format.doc

There is very little info in this about Fix16.

I dont even understand atm what they mean by: 1.8.7 fixed point.

dedndave

that's the part i do get
1.8.7 means 1, 8, and 7 bit fields
(sign bit, 8 bits value, 7 bits value)

not the way i would have expressed it, as it is a 9-bit signed value in the upper part   :P
it may be that it is not "two's compliment" form, though

dedndave

let me see if i can figure it out
and - a cup of coffee - lol

BytePtr

I would give you cup of coffee. But my hand is too short for that  :biggrin:
Im also digging in google atm what i can find out.

Currently im looking for functions like: fixedtofloat, floattofixed etc.
I think they just convert float to fixed point. The docs also say it. PS2 game cannot use floating point but PC version can.
The docs are cryptic, i know.

Maybe if i can get same values i at least have direction to move.

dedndave

i don't know why a sign bit is needed - that part doesn't make sense

BytePtr

Ok i found out that X,Y,Z can go negative down to the -7. Not more.

Sorry.

But the radius cant. Just X,Y,Z.

dedndave


BytePtr

No, this all is for newer games.

But anyway, i think i got it. It seems just some bit masking.
And of course this stuff needs more testing to be sure that it really works.

But i have changed the X offset a bit bigger and smaller and got correct results using simple AND mask.

0000001101110010   //X coordinate (6) + offset (114) = 882 in WORD
0000000001111111   // AND mask (127) to get just the offset

Result := 114

I will try to get sign also.

And im not sure if this will be so easy with radius. But i will try.

I have to eat now. Thinking about this whole day makes me hungry

BytePtr

So it seems i got the whole "thingy".

For example i need X coordinate from file.
XVALUE contains value read from map file

First i check if value is negative with this:
  mov ax, XVALUE
  and eax, $8000
  shr eax, 15
  cmp eax, 1
  jne nega
  mov @result, 1      ; its negative
  jmp fin ; get outta here
nega:
  mov @result, 0      ; not negative
fin:


Then i do this (unpack):

mov ax, XVALUE
and eax, $0ffa0
movzx eax, ax
shr eax, 7


To get X coordinate i also have to do this (if its negative):
and eax, 7

If its negative i just add - sign to my final value, not shown in here.
If its NOT negative, i skip the and eax, 7

If i need offset, i just do:
mov ax, XVALUE
movzx eax, ax
and eax, 127


And i get the offset.

For the radius, i just use AND and SHR to get the actual radius and fraction accordingly:

mov ax, RADIUSDATA
movzx eax, ax
and eax, 127    ; got my radius in eax


mov ax, RADIUSDATA
movzx eax, ax
shr eax, 7    ; got my fraction in eax



Any ideas about improving this code? Making it shorter / faster / better, anything?
Of course, i need to work on packing this data also.

Will try to figure this out also.



HOW i figured unpacking out?
Setting masks in notepad and copy paste them to windows calculator to see if i get same values from binary strings.
If i got them, i just created mask and tried the mask out. Nice way to refresh my assembler days.
0000000 000000000


000000110 0000001 //769
111111111 0100000 //65440
000000000 1111111
100000000 0000000


Negative X test:
258


100000010 value 258
000000111 mask


RADIUS:
111 1001100
111 0000000


jj2007

mov ax, RADIUSDATA
movzx eax, ax
and eax, 127    ; got my radius in eax


Try
  movzx eax, byte ptr RADIUSDATA
  and eax, 127

mov ax, RADIUSDATA
movzx eax, ax
shr eax, 7    ; got my fraction in eax


Try
  movzx eax, word ptr RADIUSDATA
  shr eax, 7

BytePtr

I will try.
It seems i can go with just one packing procedure. Seems to work for both coordinate + offset and radius + fraction.

Packing!
mov ax, CoordOrRadius
  mov dx, Fraction
  shl ax, 7
  or ax, dx ; combine the CoordOrRadius and Fraction
  movzx eax, ax

.. eax has packed value



OK. it has troubles with negative "CoordOrRadius".
Have to figure out whats wrong or its just me or it really has to be like that.


I guess i have to set the sign also.