Logs position, speed and ground flag into tables.
Compares the current values against branches.
Outputs values as text and color in TAStudio.
Tutorial on how to do:
https://www.youtube.com/watch?v=rSjOEviBHTY
--*****************--
--* Value logging *--
--*****************--
function Kirby()
players.kirby.position.x[frame] = memory.read_u16_le(0x1A22)
players.kirby.position.y[frame] = memory.read_u16_le(0x1AA2)
players.kirby.subpixel.x[frame] = memory.read_u8(0x1B23)
players.kirby.subpixel.y[frame] = memory.read_u8(0x1BA3)
players.kirby.velocity.x[frame] = memory.read_s16_le(0x1D22)
players.kirby.velocity.y[frame] = memory.read_s16_le(0x1DA2)
players.kirby.flags.midair[frame] = memory.read_u8(0x09A2)
players.kirby.flags.ground[frame] = memory.read_u8(0x0BA2)
gui.drawText(2, 168, "X: "..players.kirby.position.x[frame]..":"..players.kirby.subpixel.x[frame], 0xFFFFFFFF, 0x44FF0000)
gui.drawText(2, 180, "Y: "..players.kirby.position.y[frame]..":"..players.kirby.subpixel.y[frame], 0xFFFFFFFF, 0x4400FF00)
gui.drawText(2, 192, "Xv: "..players.kirby.velocity.x[frame], 0xFFFFFFFF, 0x44FF0000)
gui.drawText(2, 204, "Yv: "..players.kirby.velocity.y[frame], 0xFFFFFFFF, 0x4400FF00)
end
function Gooey()
players.gooey.position.x[frame] = memory.read_u16_le(0x1A24)
players.gooey.position.y[frame] = memory.read_u16_le(0x1AA4)
players.gooey.subpixel.x[frame] = memory.read_u8(0x1B25)
players.gooey.subpixel.y[frame] = memory.read_u8(0x1BA5)
players.gooey.velocity.x[frame] = memory.read_s16_le(0x1D24)
players.gooey.velocity.y[frame] = memory.read_s16_le(0x1DA4)
players.gooey.flags.midair[frame] = memory.read_u8(0x09A4)
players.gooey.flags.ground[frame] = memory.read_u8(0x0BA4)
gui.drawText(128, 168, "X: "..players.gooey.position.x[frame]..":"..players.gooey.subpixel.x[frame], 0xFFFFFFFF, 0x44FF0000)
gui.drawText(128, 180, "Y: "..players.gooey.position.y[frame]..":"..players.gooey.subpixel.y[frame], 0xFFFFFFFF, 0x4400FF00)
gui.drawText(128, 192, "Xv: "..players.gooey.velocity.x[frame], 0xFFFFFFFF, 0x44FF0000)
gui.drawText(128, 204, "Yv: "..players.gooey.velocity.y[frame], 0xFFFFFFFF, 0x4400FF00)
end
--********************--
--* TAStudio drawing *--
--********************--
--Puts text into a spezified TAStudio cell
function TAStudioText(index, column)
--Kirby
if players.kirby.velocity.x[index] ~= nil and column == "KirbyVelX"
then return tostring(players.kirby.velocity.x[index])
elseif players.kirby.velocity.y[index] ~= nil and column == "KirbyVelY"
then return tostring(players.kirby.velocity.y[index])
--Gooey
elseif players.gooey.velocity.x[index] ~= nil and column == "GooeyVelX"
then return tostring(players.gooey.velocity.x[index])
elseif players.gooey.velocity.y[index] ~= nil and column == "GooeyVelY"
then return tostring(players.gooey.velocity.y[index])
--Branches
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].kirby.position.x[index] ~= nil and column == "KirbyDx" and players.kirby.position.x[index] ~= nil and players.kirby.subpixel.x[index] ~= nil
then local d = ((players.kirby.position.x[index]*256 + players.kirby.subpixel.x[index])
- (branches[selectedbranch].kirby.position.x[index]* 256 + branches[selectedbranch].kirby.subpixel.x[index]))
* sgn(branches[selectedbranch].kirby.velocity.x[index])
return tostring(math.floor(d / 256) ..":" .. d % 256)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].kirby.position.y[index] ~= nil and column == "KirbyDy" and players.kirby.position.y[index] ~= nil and players.kirby.subpixel.y[index] ~= nil
then local d = ((players.kirby.position.y[index]*256 + players.kirby.subpixel.y[index])
- (branches[selectedbranch].kirby.position.y[index]* 256 + branches[selectedbranch].kirby.subpixel.y[index]))
* sgn(branches[selectedbranch].kirby.velocity.y[index])
return tostring(math.floor(d / 256) ..":" .. d % 256)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].gooey.position.x[index] ~= nil and column == "GooeyDx" and players.gooey.position.x[index] ~= nil and players.gooey.subpixel.x[index] ~= nil
then local d = ((players.gooey.position.x[index]*256 + players.gooey.subpixel.x[index])
- (branches[selectedbranch].gooey.position.x[index]* 256 + branches[selectedbranch].gooey.subpixel.x[index]))
* sgn(branches[selectedbranch].gooey.velocity.x[index])
return tostring(math.floor(d / 256) ..":" .. d % 256)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].gooey.position.y[index] ~= nil and column == "GooeyDy" and players.gooey.position.y[index] ~= nil and players.gooey.subpixel.y[index] ~= nil
then local d = ((players.gooey.position.y[index]*256 + players.gooey.subpixel.y[index])
- (branches[selectedbranch].gooey.position.y[index]* 256 + branches[selectedbranch].gooey.subpixel.y[index]))
* sgn(branches[selectedbranch].gooey.velocity.y[index])
return tostring(math.floor(d / 256) ..":" .. d % 256)
end
if column == "KirbyVelX" or column == "KirbyVelY" or column == "GooeyVelX" or column == "GooeyVelY"
or column == "KirbyDx" or column == "KirbyDy" or column == "GooeyDx" or column == "GooeyDy"
then return ""
end
end
function sgn(x)
if x > 0
then return 1
elseif x < 0
then return -1
else return 0
end
end
function Color(index, color1, color2)
if index >= ungreenframe
then return color1
else return color2
end
end
function ColorGradient(value, maxvalue, index)
if value < 0
then red = 255
green = 0
blue = 0
elseif value < maxvalue/2
then red = 255
green = math.floor((255/(maxvalue-maxvalue/2))*math.abs(value))
blue = 0
elseif math.abs(value) < maxvalue
then red = math.floor(-(255/(maxvalue-maxvalue/2))*math.abs(value)+510)
green = 255
blue = 0
else red = 0
green = 255
blue = 0
end
if (index >= ungreenframe)
then red = math.floor((255-red)/120*(200-240)+255)
green = math.floor((255-green)/120*(200-240)+255)
blue = math.floor((255-blue)/120*(200-240)+255)
end
alpha = 255
return alpha*256*256*256+red*256*256+green*256+blue
end
--Colors a specific TAStudio cell
function TAStudioColor(index, column)
--Kirby
if players.kirby.flags.ground[index] == 0 and column == "P1 B"
then return Color(index, 0xFFAAECFF, 0xFF00C8FF)
elseif players.kirby.velocity.x[index] ~= nil and column == "KirbyVelX"
then return ColorGradient(math.abs(players.kirby.velocity.x[index]), 512, index)
elseif players.kirby.velocity.y[index] ~= nil and column == "KirbyVelY"
then return ColorGradient(math.abs(players.kirby.velocity.y[index]), 1024, index)
--Gooey
elseif players.gooey.flags.ground[index] == 0 and column == "P2 B"
then return Color(index, 0xFFAAECFF, 0xFF00C8FF)
elseif players.gooey.velocity.x[index] ~= nil and column == "GooeyVelX"
then return ColorGradient(math.abs(players.gooey.velocity.x[index]), 512, index)
elseif players.gooey.velocity.y[index] ~= nil and column == "GooeyVelY"
then return ColorGradient(math.abs(players.gooey.velocity.y[index]), 1024, index)
--Branches
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].kirby.position.x[index] ~= nil and column == "KirbyDx" and players.kirby.position.x[index] ~= nil and players.kirby.subpixel.x[index] ~= nil
then return ColorGradient(((players.kirby.position.x[index]*256 + players.kirby.subpixel.x[index])
- (branches[selectedbranch].kirby.position.x[index]* 256 + branches[selectedbranch].kirby.subpixel.x[index]))
* sgn(branches[selectedbranch].kirby.velocity.x[index]), 256, index)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].kirby.position.y[index] ~= nil and column == "KirbyDy" and players.kirby.position.y[index] ~= nil and players.kirby.subpixel.y[index] ~= nil
then return ColorGradient(((players.kirby.position.y[index]*256 + players.kirby.subpixel.y[index])
- (branches[selectedbranch].kirby.position.y[index]* 256 + branches[selectedbranch].kirby.subpixel.y[index]))
* sgn(branches[selectedbranch].kirby.velocity.y[index]), 256, index)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].gooey.position.x[index] ~= nil and column == "GooeyDx" and players.gooey.position.x[index] ~= nil and players.gooey.subpixel.x[index] ~= nil
then return ColorGradient(((players.gooey.position.x[index]*256 + players.gooey.subpixel.x[index])
- (branches[selectedbranch].gooey.position.x[index]* 256 + branches[selectedbranch].gooey.subpixel.x[index]))
* sgn(branches[selectedbranch].gooey.velocity.x[index]), 256, index)
elseif branches[selectedbranch] ~= nil and branches[selectedbranch].gooey.position.y[index] ~= nil and column == "GooeyDy" and players.gooey.position.y[index] ~= nil and players.gooey.subpixel.y[index] ~= nil
then return ColorGradient(((players.gooey.position.y[index]*256 + players.gooey.subpixel.y[index])
- (branches[selectedbranch].gooey.position.y[index]* 256 + branches[selectedbranch].gooey.subpixel.y[index]))
* sgn(branches[selectedbranch].gooey.velocity.y[index]), 256, index)
end
end
function Ungreen(index)
if ungreenframe > index
then ungreenframe = index
end
end
--*************--
--* Log files *--
--*************--
--Load the contents from saved file on disk if it exist when loading a branch or starting the script
function LoadFile(index)
--Backup file for undo branch load
SaveFile(-1)
local file = io.open(movie.filename()..tostring(index)..".txt", "r")
local i = 0
if file ~= nil
then for line in file:lines(1) do
local s = {}
s = bizstring.split(line, ";")
--Use the same order as saving
players.kirby.position.x[i] = tonumber(s[1])
players.kirby.position.y[i] = tonumber(s[2])
players.kirby.subpixel.x[i] = tonumber(s[3])
players.kirby.subpixel.y[i] = tonumber(s[4])
players.kirby.velocity.x[i] = tonumber(s[5])
players.kirby.velocity.y[i] = tonumber(s[6])
players.kirby.flags.midair[i] = tonumber(s[7])
players.kirby.flags.ground[i] = tonumber(s[8])
players.gooey.position.x[i] = tonumber(s[9])
players.gooey.position.y[i] = tonumber(s[10])
players.gooey.subpixel.x[i] = tonumber(s[11])
players.gooey.subpixel.y[i] = tonumber(s[12])
players.gooey.velocity.x[i] = tonumber(s[13])
players.gooey.velocity.y[i] = tonumber(s[14])
players.gooey.flags.midair[i] = tonumber(s[15])
players.gooey.flags.ground[i] = tonumber(s[16])
i = i + 1
end
file:close()
end
end
--Save the current logged contents into a file and save it to disk when saving a branch or closing the script
function SaveFile(index)
local file = io.open(movie.filename()..tostring(index)..".txt", "w+")
for i = 0, movie.length(), 1 do
file:write(tostring(players.kirby.position.x[i])..";"..
tostring(players.kirby.position.y[i])..";"..
tostring(players.kirby.subpixel.x[i])..";"..
tostring(players.kirby.subpixel.y[i])..";"..
tostring(players.kirby.velocity.x[i])..";"..
tostring(players.kirby.velocity.y[i])..";"..
tostring(players.kirby.flags.midair[i])..";"..
tostring(players.kirby.flags.ground[i])..";"..
tostring(players.gooey.position.x[i])..";"..
tostring(players.gooey.position.y[i])..";"..
tostring(players.gooey.subpixel.x[i])..";"..
tostring(players.gooey.subpixel.y[i])..";"..
tostring(players.gooey.velocity.x[i])..";"..
tostring(players.gooey.velocity.y[i])..";"..
tostring(players.gooey.flags.midair[i])..";"..
tostring(players.gooey.flags.ground[i]).."\n")
end
file:close()
end
--**********************--
--* Branch opereations *--
--**********************--
--Called when a branch is loaded
function BranchLoad(index)
LoadFile(index)
end
function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
--Called when a branch is saved
function BranchSave(index)
if index >= 0
then players_ = {
kirby = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
},
gooey = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
}
}
players_ = deepcopy(players)
branches[index+1] = players_
end
SaveFile(index)
end
--Called when a branch is removed
function BranchRemove(index)
table.remove(branches, index+1)
local branches = tastudio.getbranches()
os.remove(movie.filename()..tostring(index)..".txt")
for i = index, table.getn(branches), 1 do
os.rename(movie.filename()..tostring(i+1)..".txt", movie.filename()..tostring(i)..".txt")
end
end
--Called when the script is closed
function Exit()
SaveFile(-2)
end
function FrameEnd()
gui.drawRectangle(0, 167, 255, 56, 0x88FFFFFF, 0x88000000)
gui.drawLine(128, 168, 128, 222, 0x88FFFFFF)
Kirby()
Gooey()
end
memory.usememorydomain("CARTRAM")
players = {
kirby = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
},
gooey = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
}
}
branches = {}
tastudio.addcolumn("KirbyVelX", "K Xv", 40)
tastudio.addcolumn("KirbyVelY", "K Yv", 40)
tastudio.addcolumn("GooeyVelX", "G Xv", 40)
tastudio.addcolumn("GooeyVelY", "G Yv", 40)
tastudio.addcolumn("KirbyDx", "K dx", 60)
tastudio.addcolumn("KirbyDy", "K dy", 60)
tastudio.addcolumn("GooeyDx", "G dx", 60)
tastudio.addcolumn("GooeyDy", "G dy", 60)
tastudio.onqueryitemtext(TAStudioText)
tastudio.onqueryitembg(TAStudioColor)
tastudio.ongreenzoneinvalidated(Ungreen)
ungreenframe = 0
tastudio.onbranchsave(BranchSave)
tastudio.onbranchload(BranchLoad)
tastudio.onbranchremove(BranchRemove)
event.onexit(Exit)
event.onframeend(FrameEnd)
selectedbranch = 1
for index = 1, table.getn(tastudio.getbranches())+1, 1 do
players_ = {
kirby = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
},
gooey = {position = {x = {}, y = {}},
subpixel = {x = {}, y = {}},
velocity = {x = {}, y = {}},
flags = {midair = {}, ground = {}}
}
}
local file = io.open(movie.filename()..tostring(index-1)..".txt", "r")
local i = 0
if file ~= nil
then for line in file:lines(1) do
local s = {}
s = bizstring.split(line, ";")
--Use the same order as saving
players_.kirby.position.x[i] = tonumber(s[1])
players_.kirby.position.y[i] = tonumber(s[2])
players_.kirby.subpixel.x[i] = tonumber(s[3])
players_.kirby.subpixel.y[i] = tonumber(s[4])
players_.kirby.velocity.x[i] = tonumber(s[5])
players_.kirby.velocity.y[i] = tonumber(s[6])
players_.kirby.flags.midair[i] = tonumber(s[7])
players_.kirby.flags.ground[i] = tonumber(s[8])
players_.gooey.position.x[i] = tonumber(s[9])
players_.gooey.position.y[i] = tonumber(s[10])
players_.gooey.subpixel.x[i] = tonumber(s[11])
players_.gooey.subpixel.y[i] = tonumber(s[12])
players_.gooey.velocity.x[i] = tonumber(s[13])
players_.gooey.velocity.y[i] = tonumber(s[14])
players_.gooey.flags.midair[i] = tonumber(s[15])
players_.gooey.flags.ground[i] = tonumber(s[16])
i = i + 1
end
branches[index] = players_
file:close()
end
end
LoadFile(-2)
while (true) do
frame = emu.framecount()
if frame > ungreenframe
then ungreenframe = frame
end
wasinp = inp
inp = input.get()
if inp["NumberPadPlus"] and wasinp["NumberPadPlus"] == nil and selectedbranch <= table.getn(tastudio.getbranches())
then selectedbranch = selectedbranch + 1
elseif inp["NumberPadMinus"] and wasinp["NumberPadMinus"] == nil and selectedbranch > 1
then selectedbranch = selectedbranch - 1
end
gui.pixelText(0, 160, "B:"..selectedbranch)
emu.yield()
end