--Determine game version
function detectVersion()
local value = memory.readdword(0x000093C4)
if value == 0x53554C53 then
version = "USA"
elseif value == 0x53504C53 then
version = "JPN"
else
print("Couldn't detect ROM version.")
end
end
--Read necessary RAM addresses of the corresponding version
function readStuff()
if version == "USA" then
readRNG = memory.readdword(0x00078980)
Xpos = memory.readwordsigned(0x00126BF0)
Ypos = memory.readwordsigned(0x00126BF2)
Zpos = memory.readwordsigned(0x00126BF4)
Xspawn = memory.readwordsigned(0x00126BF8)
Yspawn = memory.readwordsigned(0x00126BFA)
Zspawn = memory.readwordsigned(0x00126BFC)
Xspeed = memory.readwordsigned(0x00126B6A)
Yspeed = memory.readwordsigned(0x00126B8E)
Zspeed = memory.readwordsigned(0x00126B72)
RAMspeed = memory.readwordsigned(0x00126B86)
frameTimer = memory.readdword(0x0006CBB8)
elseif version == "JPN" then
readRNG = memory.readdword(0x00077AE0)
Xpos = memory.readwordsigned(0x00127660)
Ypos = memory.readwordsigned(0x00127662)
Zpos = memory.readwordsigned(0x00127664)
Xspawn = memory.readwordsigned(0x00127668)
Yspawn = memory.readwordsigned(0x0012766A)
Zspawn = memory.readwordsigned(0x0012766C)
Xspeed = memory.readwordsigned(0x001275DA)
Yspeed = memory.readwordsigned(0x001275FE)
Zspeed = memory.readwordsigned(0x001275E2)
RAMspeed = memory.readwordsigned(0x001275F6)
frameTimer = memory.readdword(0x0006BD54)
end
end
--RNG calculations
function RNGStep(iRNG)
local High1 = math.floor(iRNG / 65536)
local Low1 = math.floor(iRNG % 65536)
local High2 = math.floor(1103515245 / 65536)
local Low2 = math.floor(1103515245 % 65536)
local NewHigh = (High1 * Low2 + High2 * Low1) % 65536;
local NewLow = Low1 * Low2
return (NewHigh * 65536 + NewLow + 12345) % 4294967296;
--return (1103515245 * iRNG + 12345) % 4294967296
end
function RNGSteps(iRNG, steps)
for i = 1, steps do
iRNG = RNGStep(iRNG)
end
return iRNG
end
function getNumSteps(oldRNG, newRNG, maxSearch)
if oldRNG == -1 then
return -2
end
if oldRNG == newRNG then
return 0
end
for i = 1, maxSearch do
oldRNG = RNGStep(oldRNG)
if oldRNG == newRNG then
return i
end
end
return -1;
end
RNG = -1
function printRNGChanges()
newRNG = readRNG
if RNG ~= newRNG then
print(newRNG .. " (" .. getNumSteps(RNG, newRNG, 1000) .. ")")
RNG = newRNG
end
end
--Speed calculations
local prevX = nil
local prevY = nil
local prevZ = nil
local X = "N/A"
local Y = "N/A"
local Z = "N/A"
local realspeed = "N/A"
local speed = nil
local prevSpeed = nil
function speedCalc()
local currentX = Xpos
local currentY = Ypos
local currentZ = Zpos
local currentSpeed = RAMspeed * -1
if prevX ~= nil and prevY ~= nil and prevZ ~= nil then
X = currentX - prevX
Y = currentY - prevY
Z = currentZ - prevZ
realspeed = math.sqrt(X^2 + Z^2)
end
if prevSpeed ~= nil then
speed = currentSpeed - prevSpeed
if speed ~= 0 or lastSpeed ~= 0 then
print("RAM speed difference: " .. speed .. " on frame " .. frameTimer) --slightly inaccurate
end
end
prevX = currentX
prevY = currentY
prevZ = currentZ
prevSpeed = currentSpeed
lastSpeed = speed
end
--Draw it all on screen (except for RNG)
function draw()
gui.text(1, 25, "X position: " .. Xpos)
gui.text(1, 35, "Y position: " .. Ypos)
gui.text(1, 45, "Z position: " .. Zpos)
gui.text(1, 55, "X spawn point: " .. Xspawn)
gui.text(1, 65, "Y spawn point: " .. Yspawn)
gui.text(1, 75, "Z spawn point: " .. Zspawn)
gui.text(1, 85, "X speed: " .. Xspeed)
gui.text(1, 95, "Y speed: " .. Yspeed)
gui.text(1, 105, "Z speed: " .. Zspeed)
if RAMspeed ~= 0 then
gui.text(1, 115, "Horizontal RAM speed: " .. RAMspeed * -1)
else
gui.text(1, 115, "Horizontal RAM speed: " .. RAMspeed)
end
gui.text(1, 125, "Calculated speed: " .. realspeed)
end
--Main loop
function main()
detectVersion()
readStuff()
--printRNGChanges()
speedCalc()
draw()
end
emu.registerbefore(main)
gui.register(draw)