读写非标准浮点值

时间:2019-03-18 04:48:10

标签: c# floating-point hex byte reverse-engineering

我正在用C#处理二进制文件(旧视频游戏的3D模型文件)。该文件格式尚未正式记录,但其中一些已由游戏社区进行反向工程。

我在理解如何读取/写入4字节浮点值时遇到麻烦。社区成员向我提供了以下解释:

  

例如,字节EE 62 ED FF表示值-18.614。

     

字节按小端顺序排列。前2个字节代表值的小数部分,后2个字节代表值的整个部分。

     

对于小数部分,62 EE转换为小数是25326。这表示1之内的分数,也可以描述为65536/65536。因此,将25326除以65536,您将得到0.386。

     

对于整个部分,FF ED转换为十进制是65517。65517代表整数-19(即65517-65536)。

     

这使值-19 + .386 = -18.614。

这种解释大体上是合理的,但我对两件事感到困惑:

  1. 65536魔术数字有什么意义吗?
  2. BinaryWriter.Write(-18.613f)将字节写为79 E9 94 C1,所以我的假设是正在使用的二进制文件使用其专有的存储4字节浮点值的方法(即,我不能使用C#的float可互换,是否需要先对值进行编码/解码)?

2 个答案:

答案 0 :(得分:1)

首先,这不是Floating Point Number,而是Fix Point Number

注意 :定点数具有为整数部分(左侧部分保留)的特定位数(或位数)小数点后的数字)

  

魔术数65536有什么意义

它的无符号16位数字可以容纳的最大值个数,或者2^16,是有效的,因为您使用的数字是2 * 16位值,用于整数和小数部分。

  

所以我的假设是我正在使用的二进制文件使用自己的二进制文件   存储4字节浮点值的专有方法

再次没有错,。 Net 中的浮点值遵循IEEE Standard for Floating-Point Arithmetic (IEEE 754) technical standard

使用BinaryWriter.Write(float);时,基本上只是将这些位移入byte中,并将其写入Stream

uint TmpValue = *(uint *)&value;
_buffer[0] = (byte) TmpValue;
_buffer[1] = (byte) (TmpValue >> 8);
_buffer[2] = (byte) (TmpValue >> 16);
_buffer[3] = (byte) (TmpValue >> 24);
OutStream.Write(_buffer, 0, 4);

如果要读取和写入此特殊值,则需要做同样的事情,您将不得不读取和写入字节并将其转换为自己的字节

答案 1 :(得分:0)

这应该是游戏唯一的内置值。

应该更类似于Fraction Value

其中62 EE代表值的Fraction PartFF ED代表值的Whole Number Part

While Number Part很容易理解,因此我不再赘述。

Fraction Part的解释是:

每2个字节就有65536个可能性(0〜65535)。

  

256 X 256 = 65536

因此,幻数65536

游戏本身必须具有内置算法,才能将前2个字节除以65536。

选择除此以外的任何数字将是waste of memory space,结果为decreased accuracy of the value which can be represented

当然,这完全取决于游戏希望呈现的精度。