The DS uses fixed-point numbers for floats with the
Q number format, with the sign value stored in
m.
DeSmuME supports reading and writing to these, but there are two issues:
- 0.9.9 only allows for Q20.12 formatted numbers, and not for other values of
m or
n.
- Looking at the
DeSmuME lua documentation, there is no function to read these floats, which is sure inconvenient for making a script.
Either I hacked in something and backported it to 0.9.9, or used something on the lua side. I chose the latter, but nobody had written something for this, so I wrote it myself: here is the code I used (sorry, it's a bit messy.) Assumes Lua 5.1.
Download qlib.luaLanguage: lua
-- Simple binary packing function
-- To unpack, tonumber(num, 2)
function toBits(num,bits)
-- returns a table of bits, most significant first.
bits = bits or math.max(1, select(2, math.frexp(num)))
local t = {} -- will contain the bits
for b = bits, 1, -1 do
t[b] = math.fmod(num, 2)
num = math.floor((num - t[b]) / 2)
end
return table.concat(t)
end
-- https://en.wikipedia.org/wiki/Q_(number_format)#Characteristics
-- Here, the sign bit is included in m, because n+m = 32, which is equal to
-- the length of the DS adress bus
-- Unpacking function
local function Q(number, m, n)
local max = m+n
local packed = toBits(number, 32)
local sign = tonumber(string.sub(packed, 1, 1))
-- If the number is signed: NOT the number, add 1 (one's complement)
if sign == 1 then
packed = toBits(bit.bnot(tonumber(packed,2))+1,32)
end
local integer = tonumber(string.sub(packed, 2, m),2) -- As usual, Lua indexes start at 1..
local fractional = (tonumber(string.sub(packed, m+1, max), 2))/(2^n)
local total = integer + fractional
if sign == 1 then
total = total * -1
end
return total
end