Post subject: Lua reading floats
Player (33)
Joined: 3/8/2012
Posts: 398
Location: Windfall Island
This is probably really straightforward, but I'm new to this. The only functions I know of are the memory.readword() type things that all return ints. Basically I need to read 4 bytes as a float. I need it so I can reload a state and save waiting through a lot of time whenever the speed is too low to work while brute-forcing superswims.
IronSlayer wrote:
Your counterargument would be like me saying that the Earth is round and then you telling me that I need to show it's flat so I can "prove us all wrong".
Seems legit.
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
All Lua numerical types are double precision internally. So that's already covered. There isn't a native way to convert an IEEE float (4-byte) to Lua. Even internally it's using 8-bit doubles. But you can use any add-on library you can find at, say, Luaforge. Does that help?
Player (33)
Joined: 3/8/2012
Posts: 398
Location: Windfall Island
Rachelb helped me a lot with this. I ended up making a new function called memory.readfloat(address) that essentially reads the 4 bytes and converts them to float, which is converted and pushed as a string (since I'm not sure if you can even push a float). Then I just used tonumber(memory.readfloat(0xafcbbc)) which could be used. I hadn't even thought of doing it all in Dolphin until Rachel pointed out the obvious.
IronSlayer wrote:
Your counterargument would be like me saying that the Earth is round and then you telling me that I need to show it's flat so I can "prove us all wrong".
Seems legit.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
What's the point of going via the string when you end up with a double in the end? Just return a double to lua to begin with.
Player (33)
Joined: 3/8/2012
Posts: 398
Location: Windfall Island
I was unaware of being able to push a double, and pushing a string really didn't take much effort.
IronSlayer wrote:
Your counterargument would be like me saying that the Earth is round and then you telling me that I need to show it's flat so I can "prove us all wrong".
Seems legit.
Player (104)
Joined: 1/4/2013
Posts: 117
Location: Belgium
For those who are interrested, here's a lua script you can use to convert an unsigned DWord (32bits | 4bytes) to an IEEE 754 floating point.
LibHex = {}

local Vars = {}
Vars["char"] = ""
Vars["value"] = ""

Vars["ExponentOffset"] = 0
Vars["sign"] = 0
Vars["exponent"] = 0
Vars["mantissa"] = 0
Vars["temp"] = ""

LibHex.ToBin = function(hexString)
	Vars["char"] = ""
	Vars["value"] = ""	
	
	if(string.len(hexString) < 8) then
		hexString = string.gsub(string.format("%8s", hexString)," ","0")
	end
	
	for i = 1, string.len(hexString) do
	
		Vars["char"] = string.sub(hexString, i, i)
		
		if(Vars["char"] == "0") then
			Vars["value"] = Vars["value"] .. "0000"
			
		elseif(Vars["char"] == "1") then
			Vars["value"] = Vars["value"] .. "0001"
			
		elseif(Vars["char"] == "2") then
			Vars["value"] = Vars["value"] .. "0010"
			
		elseif(Vars["char"] == "3") then
			Vars["value"] = Vars["value"] .. "0011"
			
		elseif(Vars["char"] == "4") then
			Vars["value"] = Vars["value"] .. "0100"
			
		elseif(Vars["char"] == "5") then
			Vars["value"] = Vars["value"] .. "0101"
			
		elseif(Vars["char"] == "6") then
			Vars["value"] = Vars["value"] .. "0110"
			
		elseif(Vars["char"] == "7") then
			Vars["value"] = Vars["value"] .. "0111"
			
		elseif(Vars["char"] == "8") then
			Vars["value"] = Vars["value"] .. "1000"
			
		elseif(Vars["char"] == "9") then
			Vars["value"] = Vars["value"] .. "1001"
			
		elseif(Vars["char"] == "A") then
			Vars["value"] = Vars["value"] .. "1010"
			
		elseif(Vars["char"] == "B") then
			Vars["value"] = Vars["value"] .. "1011"
			
		elseif(Vars["char"] == "C") then
			Vars["value"] = Vars["value"] .. "1100"
			
		elseif(Vars["char"] == "D") then
			Vars["value"] = Vars["value"] .. "1101"
			
		elseif(Vars["char"] == "E") then
			Vars["value"] = Vars["value"] .. "1110"
			
		elseif(Vars["char"] == "F") then
			Vars["value"] = Vars["value"] .. "1111"
			
		else
			Vars["value"] = error("Unrecognize")
		end
		
	end
	
	return Vars["value"]
	
end

LibHex.BinToFloat = function (binaryString)

	Vars["ExponentOffset"] = 127
	
	Vars["exponent"] = 0
	Vars["mantissa"] = 1
	Vars["temp"] = ""
	
	if(string.sub(binaryString, 1, 1) == "0") then
		Vars["sign"] = 1
	else
		Vars["sign"] = -1
	end
	
	Vars["temp"] =  string.sub(binaryString, 2, 9) --getting binary exponent value
	for i = 1,8 do --computing it
		Vars["exponent"] = Vars["exponent"] + tonumber(string.sub(Vars["temp"],i , i)) * math.pow(2,8-i)
	end
	Vars["exponent"] = Vars["exponent"] - Vars["ExponentOffset"]
	
	if(Vars["exponent"] == Vars["ExponentOffset"] * -1) then --denormalized number
		Vars["exponent"] = -126
		Vars["mantissa"] = 0
	end
	
	Vars["temp"] = string.sub(binaryString, 10) --getting binary exponent value
	for i = 1, string.len(Vars["temp"]) do --computing it
		Vars["mantissa"] = Vars["mantissa"] + tonumber(string.sub(Vars["temp"], i, i)) * math.pow(2, i * -1)
	end
	
	if(Vars["exponent"] == Vars["ExponentOffset"]) then
		if(Vars["mantissa"] == 0) then
			return math.huge --Infinity
		else
			return math.huge * 0 --NaN (Not a Number)
		end
	end
	
	return Vars["sign"] * math.pow(2, Vars["exponent"]) * Vars["mantissa"]
end

LibHex.ToFloat = function (hexString)
	return LibHex.BinToFloat(LibHex.ToBin(hexString))
end

local x

--[[while true do

	x = memory.readdwordsigned(0xABA0E)
	x = string.format("%X",x)
	x = LibHex.ToFloat(x)
	gui.text(0, 25, string.format("Truc: %s\n", x))

	emu.frameadvance()
end]]
Note, when this is a denormalized number, you have to use %s instead of %f because there are really small numbers and lua seems to trunc after 6 digits.