-- Kirby's Adventure Sprite info viewer
-- for BizHawk
gui.defaultPixelFont("1")
-- option
viewmemory = true
spinfo = true
lvlinfo = false
actioninfo = false
subpx_as_dec = false
-- text position
local ofs_x = 152
local ofs_y = 16
local rowlgh = 16
local calmnlgh = 176
xgui = 9
ygui = 9
-- sprite set
sp_id = {}
sp_xpos = {}
sp_ypos = {}
sp_xpos_c = {}
sp_ypos_c = {}
sp_hbx1 = {}
sp_hbx2 = {}
sp_hby1 = {}
sp_hby2 = {}
sp_exist = {}
--function
gui.clearGraphics()
memory.usememorydomain("System Bus")
local lagged = false
local lagcount = 0;
local function text(a,b,c,d,e)
gui.pixelText(a-1,b-1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a ,b-1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a+1,b-1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a-1,b ,c,"#7F000000","#7F000000", "0")
gui.pixelText(a+1,b ,c,"#7F000000","#7F000000", "0")
gui.pixelText(a-1,b+1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a ,b+1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a+1,b+1,c,"#7F000000","#7F000000", "0")
gui.pixelText(a,b,c,d,e or "#7F000000")
end
local function action(st,rng)
local a = bit.band(bit.band(st,rng), 1) + memory.readbyte(0xC6DD + st) + memory.readbyte(0xC6DD + rng)
local x = memory.readbyte(0xC7DD + st) + memory.readbyte(0xC7DD + rng) - memory.readbyte(0xC7DD + math.abs(st - rng))
if memory.readbyte(0xC6DD + math.abs(st - rng)) > a then x = x - 1 end
return x
end
local function DetectLag()
local LagFlag = memory.readbyte(0x01a5)
if LagFlag == 1 then
lagged = true
elseif emu.islagged() then
lagged = true
else
lagged = false
end
end
local function DetectLag_bool()
local LagFlag = memory.readbyte(0x01a5)
if LagFlag == 1 then
return true
elseif emu.islagged() then
return true
else
return false
end
end
local function SetLag()
if tastudio.engaged() then
tastudio.setlag(emu.framecount(), lagged)
end
end
event.onmemoryexecute(DetectLag, 0xC373)
event.onmemoryexecute(SetLag, 0xC323)
local function ASL(x)
local c=0
x = x*2
if x>=256 then c=1 x=x%256 end
return x,c
end
local function LSR(x)
local c=0
x = x/2
if x%1~=0 then c=1 x=math.floor(x) end
return x,c
end
local function ROL(x,c)
x = x*2
if c==1 then x=x+1 end
if x>=256 then c=1 x=x%256 else c=0 end
return x,c
end
local function ROR(x,c)
x = x/2
if c==1 then x=x+128 end
if x%1~=0 then c=1 else c=0 end
return x,c
end
function nRNG(rng1,rng2)
local a = rng1
local c = 0
for x=0x01,0x0B do
rng1,c = ASL(rng1)
rng2,c = ROL(rng2,c)
a,c = ROL(a,c)
a,c = ROL(a,c)
a = bit.bxor(a,rng1)
a,c = ROL(a,c)
a = bit.bxor(a,rng1)
a,c = LSR(a)
a,c = LSR(a)
a = bit.bxor(a,0xFF)
a = bit.band(a,0x01)
a = bit.bor(a,rng1)
rng1 = a
end
--print(string.format("%02X %02X",rng1,rng2))
return rng1,rng2
end
function rng_advance_by(curr_h, curr_l, target_h, target_l)
local x, y = curr_h, curr_l
local count = 0
while x ~= target_h or y ~= target_l do
x, y = nRNG(x, y)
-- target is not present in the cycle
if x == curr_h and y == curr_l then
count = -1
break
end
count = count + 1
end
return count
end
function setx(a)
local low = bit.band(a, 0xFF)
local high = bit.band(bit.rshift(a, 8), 0xFF)
memory.writebyte(0x0083, low)
memory.write_s8(0x0095, high)
return a
end
addr_tileact = 0x7F00
addr_leveldata = 0x67EE
addr_hscreens = addr_leveldata + 0
addr_vscreens = addr_leveldata + 1
addr_screenlist = addr_leveldata + 8
addr_tilemap = addr_leveldata + 0xDA
addr_scrollx = 0x00EB
addr_scrolly = 0x00EA
function levelinfo()
local Cam_xpos = memory.read_s16_le(0x00DD)
local Cam_ypos = memory.read_s16_le(0x00E0)
local hscreens = memory.readbyte(addr_hscreens)
local vscreens = memory.readbyte(addr_vscreens)
local screenx = math.floor(Pl_xpos / 256)
local screeny = math.floor(Pl_ypos / 192)
local scrollx = memory.readbyte(addr_scrollx)
local scrolly = memory.readbyte(addr_scrolly)
--print(Pl_xpos 256)
--print(screeny)
--for i = 0, vscreens do
--for j = 0, hscreens do
for y = 0, 12 - 1 do
for x = 0, 16 - 1 do
local xp = x * 16
local yp = y * 16
local tile = memory.readbyte(addr_tilemap + ((screeny * 12) + y) * 16 + x)
local tileattr = memory.readbyte(addr_tileact + tile)
local box_x = xp + (screenx * 256) - Cam_xpos
local box_y = yp + (screeny * 192) - Cam_ypos - 8
if tileattr == 0x0D then
gui.drawRectangle(box_x, box_y, 16, 16, 0xFF000000)
end
--gui.pixelText(xp - Cam_xpos ,yp - Cam_ypos - 8, tostring(tileattr), nil, 0x7F000000, "1")
--gui.pixelText(Pl_xpos - Cam_xpos - 8, Pl_ypos - Cam_ypos - 16, tostring(kact), nil, 0xFFC60000, "1")
end
end
--end
--end
end
lastx = 0
lasty = 0
function viewmemory()
Pl_xpos = memory.read_u8(0x0083) + memory.read_u8(0x0095) * 256
Pl_ypos = memory.read_u8(0x00B9) + memory.read_u8(0x00CB) * 256
local Pl_xspx = memory.read_u8(0x0071)
local Pl_yspx = memory.read_u8(0x00A7)
local Pl_xspd = memory.read_s16_le(0x05B9)
local Pl_yspd = memory.read_s16_le(0x05BD)
if subpx_as_dec then
gui.pixelText(xgui,ygui,string.format("%d.%3d",Pl_xpos,math.floor((Pl_xspx / 256.0)* 1000)),nil,0x7F000000, "0")
gui.pixelText(xgui+48,ygui,string.format("%d.%3d",Pl_ypos,math.floor((Pl_yspx / 256.0) * 1000)),nil,0x7F000000, "0")
else
gui.pixelText(xgui,ygui,string.format("%d.%02X",Pl_xpos,Pl_xspx),nil,0x7F000000, "0")
gui.pixelText(xgui+48,ygui,string.format("%d.%02X",Pl_ypos,Pl_yspx),nil,0x7F000000, "0")
end
gui.pixelText(xgui,ygui+12,string.format("%+d",Pl_xspd),nil,0x7F000000, "0")
gui.pixelText(xgui+48,ygui+12,string.format("%+d",Pl_yspd),nil,0x7F000000, "0")
gui.pixelText(xgui,ygui+24,string.format("(%+d)",Pl_xpos - lastx),nil,0x7F000000, "0")
gui.pixelText(xgui+48,ygui+24,string.format("(%+d)",Pl_ypos - lasty),nil,0x7F000000, "0")
local rng1 = memory.readbyte(0x003E)
local rng2 = memory.readbyte(0x003F)
gui.pixelText(xgui+96,ygui,string.format("%02X %02X",rng1,rng2),nil,0x7F000000, "0")
if actioninfo then
for i = 0,15 do
rng1,rng2 = nRNG(rng1,rng2)
text(xgui,60+i*8,string.format("%02X %02X %d %d",rng1,rng2,action(0x04,rng1,rng2), bit.band(rng1,7)))
text(212,48+i*8,string.format("%02X %02X %d",rng1,rng2,action(0x04,rng1,rng2)))
end
end
lastx = Pl_xpos
lasty = Pl_ypos
end
function spriteinfo()
local Cam_xpos = memory.read_s16_le(0x00DD)
local Cam_ypos = memory.read_s16_le(0x00E0)
local exist_str = ""
local exist_count = 0
for i = 0, 8 do
sp_id[i+1] = i
sp_xpos[i+1] = memory.read_u8(0x008B + i) + memory.read_u8(0x009D + i) * 256
sp_ypos[i+1] = memory.read_u8(0x00C1 + i) + memory.read_u8(0x00D3 + i) * 256
sp_xpos_c[i+1] = sp_xpos[i+1] - Cam_xpos
sp_ypos_c[i+1] = sp_ypos[i+1] - Cam_ypos
sp_hbx1[i+1] = -8
sp_hbx2[i+1] = 8
sp_hby1[i+1] = -16
sp_hby2[i+1] = 0
sp_exist[i+1] = memory.read_u8(0x62AB + i)
local exists = 0
if sp_exist[i+1] ~= 0x80 then
exists = 1
exist_count = exist_count + 1
gui.drawRectangle(sp_xpos_c[i+1] + sp_hbx1[i+1], sp_ypos_c[i+1] + sp_hby1[i+1], sp_hbx2[i+1] - sp_hbx1[i+1], sp_hby2[i+1]-sp_hby1[i+1], 0x6A0000FF)
gui.pixelText(sp_xpos_c[i+1]-8, sp_ypos_c[i+1], string.format("%X", sp_id[i+1]))
gui.pixelText(xgui + 180, ygui + 2 + (7 * exist_count), string.format("%X: %d, %d", (0x62AB + i), sp_xpos[i+1], sp_ypos[i+1]))
end
exist_str = exist_str .. exists
end
--gui.pixelText(xgui+180,ygui,exist_str,nil,0xAF000000, "0")
gui.drawRectangle(Pl_xpos - Cam_xpos - 8, Pl_ypos - Cam_ypos - 16, 16, 16, 0xFFC60000)
end
togglelag = true
local lcount = 0
function resetlagcount()
lcount = 0
return lcount
end
function lagcount()
if DetectLag_bool() then
lcount = lcount + 1
end
gui.pixelText(xgui,ygui+36,string.format("(%+d)",lcount),nil,0x7F000000, "0")
end
-- Main
while true do
if viewmemory then
viewmemory()
end
if spinfo then
spriteinfo()
end
if lvlinfo then
levelinfo()
end
if togglelag then
lagcount()
end
--local level = memory.read_s16_le(0x0562)
--gui.pixelText(8, 176+8, string.format("Level %03X", level), nil, 0xAF000000, "0")
emu.frameadvance()
end