TAStudio coloring, map generator and drawing it on canvas.
Works on Bizhawk 2.3.2
memory.usememorydomain("Combined WRAM")
-- Generates a 24bpp bitmap .bmp file, without colormasks and colortables and is uncompressed
-- Blue Green Red byte order!
-- latest known working Bizhawk version: 2.3.2
function GenerateMapImage()
local width = memory.read_u16_le(0x422A0)
local height = memory.read_u16_le(0x422A2)
local ptr = memory.read_u32_le(0x4229C)-0x2000000
local mapID = memory.read_u8(0x424D0)
local ROMname = gameinfo.getromname()
local file = io.open(ROMname.."-"..mapID..".bmp", "wb")
local BitMapFileHeader = {0x42, 0x4D, --bfType
0x00, 0x00, 0x00, 0x00, --bfSize
0x00, 0x00, 0x00, 0x00, --bfReserved
0x36, 0x00, 0x00, 0x00} --bfOffBits
local BitMapInfoHeader = {0x28, 0x00, 0x00, 0x00, --biSize
0x00+width, 0x00, 0x00, 0x00, --biWidth
--0x00+height, 0x00, 0x00, 0x00, --biWidth
(0xFF-height+1)%256, 0xFF, 0xFF, 0xFF, --biHeight
0x01, 0x00, --biPlanes
0x18, 0x00, --biBitCount
0x00, 0x00, 0x00, 0x00, --biCompression
0x10, 0x00, 0x00, 0x00, --biSizeImage
0x00, 0x00, 0x00, 0x00, --biXPelsPerMeter
0x00, 0x00, 0x00, 0x00, --biYPelsPerMeter
0x00, 0x00, 0x00, 0x00, --biClrUsed
0x00, 0x00, 0x00, 0x00, --biClrImportant
}
file:write(string.char(unpack(BitMapFileHeader)))
file:write(string.char(unpack(BitMapInfoHeader)))
for i = 0, height-1, 1 do
for j = 0, width-1, 1 do
local PictureData = {}
local tile = memory.read_u8(ptr+j+i*width)
local red = bit.rshift(bit.band(tileTable[tile],0x00FF0000), 16)
local green = bit.rshift(bit.band(tileTable[tile],0x0000FF00), 8)
local blue = bit.band(tileTable[tile],0x000000FF)
--collisionPtr+j+i*width
PictureData[1] = blue
PictureData[2] = green
PictureData[3] = red
file:write(string.char(unpack(PictureData)))
end
if width % 4 ~= 0
then local k = (width % 4)
for j = 1, k, 1 do
file:write(string.char(0))
end
end
end
file:close()
end
function Map()
canvas.Clear("white")
local ptr = memory.read_u32_le(0x04347C)--0x02000000
--04347C w h 0 Combined WRAM player ptr
local xCam=memory.read_u16_le(0x042112)
local yCam=memory.read_u16_le(0x042114)
local collisionPtr = memory.read_u32_le(0x4229C)--0x02000000
local width = memory.read_u16_le(0x422A0)
local height = memory.read_u16_le(0x422A2)
local mapID = memory.read_u8(0x424D0)
local ROMname = gameinfo.getromname()
--if collisionPtr > 0x020FFFFF
--then done = false
--end
local mX = canvas.GetMouseX()
local mY = canvas.GetMouseY()
local mButt = input.getmouse()
if mX >= 0 and mX <= 500 and mY >= 0 and mY <= 500
then if mButt["Left"]
then --xOffset = (xCam)*zoom
--yOffset = (yCam)*zoom
-- zoom = --1
elseif mButt["Right"]
then dmx = mX - old_mX
dmy = mY - old_mY
xOffset = xOffset + dmx
yOffset = yOffset + dmy
elseif mButt["XButton1"]
then local zx = mX
local zy = mY
local vx = (zx-xOffset)/zoom
local vy = (zy-yOffset)/zoom
zoom = zoom*1.01
xOffset = xOffset -(vx -(zx-xOffset)/zoom)*zoom
yOffset = yOffset -(vy -(zy-yOffset)/zoom)*zoom
done = false
elseif mButt["XButton2"]
then local zx = mX
local zy = mY
local vx = (zx-xOffset)/zoom
local vy = (zy-yOffset)/zoom
zoom = zoom*0.99
if zoom < 1
then zoom = 1
end
xOffset = xOffset -(vx -(zx-xOffset)/zoom)*zoom
yOffset = yOffset -(vy -(zy-yOffset)/zoom)*zoom
done = false
end
-- canvas.DrawText(0, 0, tostring((mX-xOffset)/zoom).."\n"..tostring((mY-yOffset)/zoom), 0xFFFF0000, 0xFF00FF00)
end
old_mX = mX
old_mY = mY
gui.drawText(10,100, string.format("%X",ptr))
if collisionPtr <= 0x020FFFFF ---and collisionPtr <= 0x08000000--and not done
then local file = io.open(ROMname.."-"..mapID..".bmp", "rb")
if file == nil
then canvas.clearImageCache()
GenerateMapImage()
print("new Image: "..ROMname.."-"..mapID..".bmp generated.")
else canvas.DrawImage(ROMname.."-"..mapID..".bmp", xOffset, yOffset, width*zoom, height*zoom)
file:close()
end
--done = true
if collisionPtr > 0x020FFFFF
then return
end
-- print("nooooooooooooooooo")
local si = math.max(0, math.floor(-yOffset/zoom))
local sj = math.max(0, math.floor(-xOffset/zoom))
local ei = math.min(height-1, math.floor((500-yOffset)/zoom))
local ej = math.min(width-1, math.floor((500-xOffset)/zoom))
--[[
for i = si, ei, 1 do --height
for j = sj, ej, 1 do --width
if (xOffset+j*zoom >= 0-zoom and xOffset+j*zoom <= 500+zoom) and (yOffset+i*zoom >= 0-zoom and yOffset+i*zoom <= 500+zoom)
then local tile = memory.read_u8(collisionPtr-0x02000000+j+i*width)
canvas.DrawRectangle(xOffset+j*zoom ,yOffset+i*zoom , zoom, zoom, tileTable[tile],tileTable[tile])
end
done = true
end
end
]]
end
--[[
//Draw objects
while ptr ~= 0 do
local p = ptr - 0x02000000
if ptr == 0
then break
end
local index = memory.read_u16_le(ptr)
local xPos = memory.read_u16_le(p+16)
local yPos = memory.read_u16_le(p+18)
local xOnS = memory.read_u16_le(p+22)
local yOnS = memory.read_u16_le(p+24)
local yPt1 = memory.read_u16_le(p+30)
local yPt2 = memory.read_u16_le(p+32)
local xPt1 = memory.read_u16_le(p+34)
local xPt2 = memory.read_u16_le(p+36)
ptr = memory.read_u16_le(p+128)
if ptr == 0
then break
end
canvas.DrawBox(xOffset+xPt1*zoom/8, yOffset+yPt1*zoom/8, xOffset+xPt2*zoom/8, yOffset+yPt2*zoom/8, 0x88FF0000, 0x55FF0000)
canvas.DrawAxis(xOffset+xPos*zoom/8, yOffset+yPos*zoom/8, 5)
--canvas.DrawText(xPos*zoom/8-xOffset,yPos*zoom/8-yOffset,string.format("%X",ptr))
end
]]
canvas.Refresh()
end
function GenerateMapTable()
local collisionPtr = memory.read_u32_le(0x4229C)-0x2000000
local width = memory.read_u16_le(0x422A0)
local height = memory.read_u16_le(0x422A2)
for i = 0, height-1, 1 do
---MapTable[i] = {}
for j = 0, width-1, 1 do
MapTable[j+i*width] = memory.read_u8(collisionPtr+j+i*width)
end
end
end
function GetColorFromValue(value, maxValue, index)
if value ~= nil
then if math.abs(value) < maxValue/1
then red = 255
green = math.floor((255/maxValue/1)*math.abs(value))
blue = 0
else red = math.floor(-(255/maxValue/1)*math.abs(value)+510)
green = 255
blue = 0
end
if (index >= ug)
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
return red*256*256+green*256+blue
end
end
function Color(index, column)
if column == "Right" and xSpdTable[index] ~= nil
then if xSpdTable[index] > 0
then color = GetColorFromValue(xSpdTable[index], 2.2, index)
return color
end
elseif column == "Left" and xSpdTable[index] ~= nil
then if xSpdTable[index] < 0
then color = GetColorFromValue(xSpdTable[index], 2.2, index)
return color
end
elseif column == "Down" and ySpdTable[index] ~= nil
then if ySpdTable[index] > 0
then color = GetColorFromValue(ySpdTable[index], 1.466667, index)
return color
end
elseif column == "Up" and ySpdTable[index] ~= nil
then if ySpdTable[index] < 0
then color = GetColorFromValue(ySpdTable[index], 1.466667, index)
return color
end
elseif column == "B" and jmpTable[index] ~= nil
then if jmpTable[index] == 1
then if index >= ug
then return 0xAAECDD
else return 0x00C8FF
end
else
end
end
end
function Ungreen(index)
if ug > index
then ug = index
end
end
function BranchLoad(index)
local file = io.open(movie.filename()..tostring(index)..".txt", "r")
local num = 0
for i in file:lines(1) do
local str = {}
str = bizstring.split(i, ";")
xSpdTable[num] = tonumber(str[1])
ySpdTable[num] = tonumber(str[2])
jmpTable[num] = tonumber(str[3])
num = num + 1
end
file:close()
end
function BranchSave(index)
local file = io.open(movie.filename()..tostring(index)..".txt", "w+")
for i = 0, ug, 1 do
file:write(tostring(xSpdTable[i])..";"..tostring(ySpdTable[i]).."\n"..tostring(jmpTable[i]).."\n")
end
file:close()
end
function Exit()
local file = io.open(movie.filename().."c.txt", "w+")
for i = 0, ug, 1 do
file:write(tostring(xSpdTable[i])..";"..tostring(ySpdTable[i]).."\n"..tostring(jmpTable[i]).."\n")
end
file:close()
end
function FrameEnd()
xPos = memory.readfloat(0x3B40, false)
yPos = memory.readfloat(0x3B44, false)
xSpd = memory.readfloat(0x3B48, false)
ySpd = memory.readfloat(0x3B4C, false)
gui.drawText(2, 36, "Xp:"..xPos.." ", 0xFFFFFFFF, 0x77990000);
gui.drawText(2, 51, "Yp:"..yPos.." ", 0xFFFFFFFF, 0x77009900);
gui.drawText(2, 66, "Xv:"..xSpd.." ", 0xFFFFFFFF, 0x77990000);
gui.drawText(2, 81, "Yv:"..ySpd.." ", 0xFFFFFFFF, 0x77990000);
jumpFlag = memory.read_u8(0x43a94)
xSpdTable[f] = xSpd
ySpdTable[f] = ySpd
jmpTable[f] = jumpFlag
end
xSpdTable = {}
ySpdTable = {}
jmpTable = {}
tileTable = {}
tileTable[0x0] = 0xFF222222 -- wall
tileTable[0x1] = 0xFFCCCCCC -- floor
tileTable[0x2] = 0xFF999999 -- stone
tileTable[0x3] = 0xFF000033 -- water
tileTable[0x4] = 0xFF5555FF -- water
tileTable[0x5] = 0xFF333333 -- wall
tileTable[0x6] = 0xFF333333 -- wall
tileTable[0x7] = 0xFF000000 -- void
tileTable[0xB] = 0xFF00FFFF -- mushroom
tileTable[0x20] = 0xFF1234FF -- entrance/exit
tileTable[0x21] = 0xFF1234FF -- entrance/exit
tileTable[0x22] = 0xFF1234FF -- entrance/exit
tileTable[0x23] = 0xFF1234FF -- entrance/exit
tileTable[0x40] = 0xFF5500FF -- section change underground
tileTable[0x41] = 0xFF8800FF -- section change underground
tileTable[0xFF] = 0xFF333333 -- wall?
ug = 0
canvas = gui.createcanvas(500, 500)
done = false
zoom = 10
dmx = 0
dmy = 0
xOffset = 0
yOffset = 0
old_mX = 0
old_mY = 0
xFollow = 0
yFollow = 0
MapTable = {}
tastudio.onqueryitembg(Color)
tastudio.ongreenzoneinvalidated(Ungreen)
tastudio.onbranchload(BranchLoad)
tastudio.onbranchsave(BranchSave)
event.onexit(Exit)
event.onframeend(FrameEnd)
local file = io.open(movie.filename().."c.txt", "r")
if file ~= nil
then local num = 0
for i in file:lines(1) do
local str = {}
str = bizstring.split(i, ";")
xSpdTable[num] = tonumber(str[1])
ySpdTable[num] = tonumber(str[2])
jmpTable[num] = tonumber(str[3])
num = num + 1
end
file:close()
end
--GenerateMapTable()
while true do
--ptr = memory.read_u16_le(0x04347C)
--04347C w h 0 Combined WRAM player ptr
--xCam=memory.read_u16_le(0x042112)
--yCam=memory.read_u16_le(0x042114)
-- repeat
-- local index = memory.read_u16_le(ptr)
-- local xPos = memory.read_u16_le(ptr+16)
-- local yPos = memory.read_u16_le(ptr+18)
-- local xOnS = memory.read_u16_le(ptr+22)
-- local yOnS = memory.read_u16_le(ptr+24)
-- local yPt1 = memory.read_u16_le(ptr+30)
-- local yPt2 = memory.read_u16_le(ptr+32)
-- local xPt1 = memory.read_u16_le(ptr+34)
-- local xPt2 = memory.read_u16_le(ptr+36)
-- ptr = memory.read_u16_le(ptr+128)
-- --gui.drawBox(xPt1-xCam, yPt1-yCam, xPt2-xCam, yPt2-yCam, 0x88FF0000, 0x55FF0000)
-- --gui.drawAxis(xOnS,yOnS,5)
-- until ptr == 0
f = emu.framecount()
if f > ug
then ug = f
end
Map()
emu.yield();
end
--[[
player
003AF4 w u 0 EWRAM index? -3b74=0x80
003AF6 w u 0 EWRAM ?
003AF8 w u 0 EWRAM ?
003AFA w u 0 EWRAM palette
003AFC w u 0 EWRAM y old
003AFE w u 0 EWRAM action
003B00 w u 0 EWRAM x
003B02 w u 0 EWRAM y
003B04 w u 0 EWRAM ?
003B06 w u 0 EWRAM x on s
003B08 w u 0 EWRAM y on s
003B0A w u 0 EWRAM ?
003B0C w u 0 EWRAM ?
003B0E w u 0 EWRAM pt y
003B10 w u 0 EWRAM pt y
003B12 w u 0 EWRAM pt x
003B14 w u 0 EWRAM pt x
position calculation variables?
003B40 w u 0 EWRAM x sub
003B42 w u 0 EWRAM x
003B44 w u 0 EWRAM y sub
003B46 w u 0 EWRAM y
003B48 w u 0 EWRAM x v sub
003B4A w s 0 EWRAM x v
003B4C w u 0 EWRAM y v sub
003B4E w u 0 EWRAM y v
003B70 w h 0 EWRAM ptr
]]--