读取和写入非标准浮点值

问题描述 投票:0回答:2

我正在使用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并且需要编码/解码价值第一)?
c# floating-point hex byte reverse-engineering
2个回答
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);时,它基本上只是将位移到bytes并将其写入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);

如果你想读取和写入这个特殊值,你需要做同样的事情,你将不得不读取和写入字节并将它们转换为你自己


0
投票

这应该是游戏独有的内置价值。

它应该更像Fraction Value

其中62 EE代表价值的Fraction Part,而FF 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

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

© www.soinside.com 2019 - 2024. All rights reserved.