User File #41553898387519790

Upload All User Files

#41553898387519790 - Zook Man ZX4 - Baisc script, now with a visualizer.

ZookManZX4.lua
770 downloads
Uploaded 9/6/2017 8:58 AM by FatRatKnight (see all 245)
There is an array at 7C44 that gets filled when objects are allocated, and freed up when objects are removed.
Colors:
Black - Free
Cyan - Player bullet
Green - Item
Yellow - Enemy (w/ 0+ HP reported)
Purple - Enemy (w/ negative HP reported)
Red - No detected object -- Memory leak likely
The more filled the bar, the more likely the lag. At least, that's the idea I want to transmit.
... I'm just not feeling rather vocal right now.
memory.usememorydomain("IWRAM")
local R4u= memory.read_u32_le
local R4s= memory.read_s32_le
local R2u= memory.read_u16_le
local R2s= memory.read_s16_le
local R1u= memory.read_u8
local R1s= memory.read_s8
local R4x= function(a) return string.format("%X",R4u(a)) end
local R2x= function(a) return string.format("%X",R2u(a)) end

local RAMList2= { --Includes method and color.
-- Address  Type  Color
--  {a=0x15DC,m=R4s,c=0xFFC0C0C0}, --Laser shots
--  {a=0x16DC,m=R2s,c=0xFFFFFF00}, --Miniboss state
--  {a=0x15F0,m=R4s,c=0xFFC0C0C0}, --Action lock
  {a=0x15DC,m=R4s,c=0xFFFFFFFF}, --Weapon shot count
  {a=0x1514,m=R4x,c=0xFFFFFFFF}, --Screen motion flags
  {a=0x1EA4,m=R2s,c=0xFFFFFF00}, --Flame charge timer
  {a=0x1504,m=R4s,c=0xFFFFFFFF}, --Camera Y
  {a=0x1E5C,m=R2s,c=0xFFFFFFFF}, --Player screen location Y
  {a=0x1500,m=R4s,c=0xFFFFFFFF}, --Camera X
  {a=0x1E58,m=R2s,c=0xFFFFFFFF}, --Player screen location X
  {a=0x17A0,m=R4x,c=0xFFFFFFFF}, --Frame counter
  {a=0x1530,m=R4s,c=0xFF00FFFF}, --Segment
--  {a=0x153C,m=R4s,c=0xFF0080FF}, --Segment width
--  {a=0x1540,m=R4s,c=0xFF0080FF}, --Segment height
  {a=0x15E0,m=R4s,c=0xFFFFFFFF}, --Shot cooldown
  {a=0x1608,m=R4s,c=0xFFFFFFFF}, --Charge counter
  {a=0x1E6C,m=R2s,c=0xFF00FF00}, --Jump frames (object data: player)
  {a=0x16E0,m=R4s,c=0xFFC0C0C0}, --Miniboss invincibility timer
  {a=0x16F8,m=R4s,c=0xFFC0C0C0}, --Boss invincibility timer
  {a=0x1708,m=R4s,c=0xFFFF8000}, --Boss HP main
  {a=0x170C,m=R4s,c=0xFFFF8000}, --Boss HP sub
}

local RAMList= {
    0x15E0, --Shot cooldown
    0x1608, --Charge counter
    0x1530, --Segment counter
    0x153C, --Segment width
    0x1540  --Segment height
}

--*****************************************************************************
local function PixelTextRight(x,y,t,c1,c2,f)
--*****************************************************************************
--Specify right pixel instead of left pixel to position our text.
--Should be handy in keeping our numbers relatively readable.

    x= x - 4*(#tostring(t))
    gui.pixelText(x,y,t,c1,c2,f)
end

--*****************************************************************************
local function FetchAddrDomainGBA(a)
--*****************************************************************************
--I am furious at the design away from the bus. It used to exist! Why remove?
--I do not want to code in removing offsets to pointers every time I read one.
--This function was made because I insist on full pointers. Has only what I know.

    if     (a >= 0x02000000) and (a < (0x02000000+memory.getmemorydomainsize("EWRAM"))) then
        return a-0x02000000, "EWRAM"
    elseif (a >= 0x03000000) and (a < (0x03000000+memory.getmemorydomainsize("IWRAM"))) then
        return a-0x03000000, "IWRAM"
    elseif (a >= 0x08000000) and (a < (0x08000000+memory.getmemorydomainsize("ROM"))) then
        return a-0x08000000, "ROM"
    else
        error("Unknown address " .. a,2)
    end
end

--[[
1EA4,2s - Flame charge timer
]]--

local ObjColors= {
[0]=0xFFC0C0C0, -- 0,Weapon selection icon
    0xFF20FF20, -- 1,Player
    0xFFC0C0C0, -- 2,Life icon
    0xFFC0C0C0, -- 3,HP bar
    0xFFC0C0C0, -- 4,Weapon bar
    0xFFFFFFFF, -- 5,
    0xFFC0C0C0, -- 6,Dust sprite
    0xFFC0C0C0, -- 7,Dust sprite
    0xFFC0C0C0, -- 8,Dust sprite
    0xFFC0C0C0, -- 9,Dust sprite
    0xFF00FF00, --10,Charge sprite
    0xFFFFFFFF, --11,
    0xFFFFFFFF, --12,
    0xFFFFFFFF, --13,
    0xFFFFFFFF, --14,
    0xFFFFFFFF, --15,
    0xFFFFFFFF, --16,
    0xFFFFFFFF, --17,
    0xFFFFFFFF, --18,
    0xFFC0C0C0, --19,Player muzzle flash
    0xFF00FFFF, --20,Player projectile
    0xFF00FFFF, --21,Player projectile
    0xFF00FFFF, --22,Player projectile
    0xFF00FFFF, --23,Player projectile
    0xFF00FFFF, --24,Player projectile
    0xFF00FFFF, --25,Player projectile
    0xFF00FFFF, --26,Player projectile
    0xFF00FFFF, --27,Player projectile
    0xFF00FFFF, --28,Player projectile (?)
    0xFF00FFFF, --29,Player projectile (?)
    0xFFFFFF00, --30,Enemy
    0xFFFFFF00, --31,Enemy
    0xFFFFFF00, --32,Enemy
    0xFFFFFF00, --33,Enemy
    0xFFFFFF00, --34,Enemy
    0xFFFFFF00, --35,Enemy
    0xFFFFFF00, --36,Enemy
    0xFFFFFF00, --37,Enemy
    0xFFFFFF00, --38,Enemy
    0xFFFFFF00, --39,Enemy
    0xFFFFFF00, --40,Enemy
    0xFFFFFF00, --41,Enemy
    0xFFFFFF00, --42,Enemy
    0xFFFFFF00, --43,Enemy
    0xFFFFFF00, --44,Enemy
    0xFFFFFF00, --45,Enemy
    0xFFFFFF00, --46,Enemy
    0xFFFFFF00, --47,Enemy
    0xFFFFFF00, --48,Enemy
    0xFFFFFF00, --49,Enemy
    0xFFFFC000, --50,
    0xFFFFC000, --51,
    0xFFFFC000, --52,
    0xFFFFC000, --53,
    0xFFFFC000, --54,
    0xFFFFC000, --55,
    0xFFFFC000, --56,
    0xFFFFC000, --57,
    0xFFFFC000, --58,
    0xFFFFC000, --59,
}

--*****************************************************************************
local function DrawBlocks(x,y,a)
--*****************************************************************************
--This idea failed.
--Thought those pointers may have led to something boxy or whatever.
--Instead, we have a mess. But at least it isn't hitting the PANIC.

    local PANIC= 0
    while R2s(a,"ROM") ~= -1 do
        local bX,bY= R1s(a,"ROM"),R1s(a+1,"ROM")
        bX= bX*4+x; bY= bY*4+y
        gui.drawRectangle(bX,bY,4,4,0x60FF00FF,0x60FFFF00)
        a= a+2
        PANIC=PANIC+1; if PANIC > 400 then error("PANIC") end --Just in case
    end
end
--[[Piece of the failed idea
    local ID= R2s(addr+0x08)
    local ptr= R4u(addr+0x70)
    if (ID ~= 0) and (ptr ~= 0) then
        BlockPtr= R4u( FetchAddrDomainGBA(ptr + (ID-1)*4) )
        if BlockPtr > 0x08000000 then --Really should be in the ROM.
            DrawBlocks(X,Y,BlockPtr-0x08000000)
        end
    end
]]--

--*****************************************************************************
local function ObjList()
--*****************************************************************************
--Displays some information on objects.
--Well, more like a specific stat.

  local ObjCount= 0
  for i= 0, 59 do
    local addr= 0x1DE4 + 0x74*i
    local X= R4s(addr+0x00)
    local Y= R4s(addr+0x04)
    local clr= ObjColors[i] or 0xFFFF00FF --List really should be complete...

--    if R2s(addr+0x0A) ~= 0 then
      gui.pixelText(X,Y   ,string.format("%d",R2s(addr+0x2C)),clr)
      gui.pixelText(X,Y+ 7,R2x(addr+0x1C),clr)
--      gui.pixelText(X,Y+14,string.format("%04X",addr),clr)
--    end
    if R2s(addr+0x0A) ~= 0 then ObjCount= ObjCount+1 end
  end
  gui.pixelText(10,153,ObjCount)
end

local AssignmentArrayColors= {}
local function ResetColors() for i= 0, 0xBF do AssignmentArrayColors[i]= 0xFFFF0000 end end

--*****************************************************************************
local function NullFn() end  --Do not process.
--*****************************************************************************

--*****************************************************************************
local function DoPlyr(addr,x,y)
--*****************************************************************************
--Player stuff. Potentially useful addresses:
--00,4s - Screen position X
--04,4s - Screen position Y
--08,2x - Sprite ID
--10,2u - Action Timer (?)

  gui.pixelText(x,y   ,string.format("%d",R2s(addr+0x08)),0xFF00FF20)
  gui.pixelText(x,y+ 7,string.format("%d",R2s(addr+0x10)),0xFF00FF20)
  gui.pixelText(x,y+14,(R4u(0x17A0)-1)%4,0xFFFFFFFF) --Frame counter
  --gui.pixelText(x,y+21,string.format("%08X",R4u(addr+0x70)),0xFFFFFFFF) --Ptr
end

local Bcount= 0
--*****************************************************************************
local function DoBllt(addr,x,y)
--*****************************************************************************
--Player bullets.
--1C: Frames existed
--48: Damage

  if R2s(addr+0x08) == 0 then return end
  Bcount= Bcount+1 

  local ArrayStart= math.floor((R2u(addr+0x0E)-256)/4)
  local ArrayCount= R2u(addr+0x40)
  for i= ArrayStart, ArrayStart+ArrayCount-1 do
    AssignmentArrayColors[i]= 0xFF00FFFF
  end

  gui.pixelText(x,y   ,string.format("%d",R2s(addr+0x1C)),0xFF00FFFF)
  gui.pixelText(x,y+ 7,string.format("%d",R2s(addr+0x48)),0xFF00FFFF)
--  gui.pixelText(x,y   ,string.format("%d",R2s(addr+0x08)),0xFF00FFFF)
--  gui.pixelText(x,y+ 7,string.format("%d",R2s(addr+0x10)),0xFF00FFFF)
--  gui.pixelText(x,y+14,string.format("%08X",R4s(addr+0x70)),0xFF00FFFF)
end

local Ecount= 0
--*****************************************************************************
local function DoOthr(addr,x,y)
--*****************************************************************************
--Enemy data.
--I would like a way to know when things exist.
--I'm guessing it's 0x0A, so I'll do that. Please let me know false negatives.
--Would love a way to recognize who I'm looking at.
--2C - Enemy HP
--58 - Invincibility timer

  if R2s(addr+0x0A) == 0 then return end
  Ecount= Ecount+1

  local clr= 0xFFFFFFFF

  if R2s(addr+0x3C) == 2 then --Item?
    gui.pixelText(x,y  ,string.format("%d",R2s(addr+0x1C)),0xFF000000,0xFF00FF00) --Timer
    gui.pixelText(x,y+7,string.format("%d",R2s(addr+0x0A)),0xFF000000,0xFF00FF00) --ID
    clr= 0xFF00FF00

  elseif R2s(addr+0x2C) ~= -1 then --Has HP
    gui.pixelText(x,y  ,string.format("%d",R2s(addr+0x2C)),0xFFFF8000) --HP
    gui.pixelText(x,y+7,string.format("%d",R2s(addr+0x58)),0xFFFF8000) --Inv.Timer
--    gui.pixelText(x,y+14,string.format("%04X",addr),0xFFFF8000) --addr
--    gui.pixelText(x,y  ,string.format("%d",R2s(addr+0x08)),0xFFFF8000) --Spr
--    gui.pixelText(x,y+7,string.format("%02X",R2s(addr+0x14)),0xFFFF8000) --ID
    clr= 0xFFFFFF00

  else --Can't be damaged
    gui.pixelText(x,y  ,string.format("%d",R2s(addr+0x1C)),0xFF000000,0xFFFF8000) --Timer
    gui.pixelText(x,y+7,string.format("%d",R2s(addr+0x08)),0xFF000000,0xFFFF8000) --Sprite

    clr= 0xFFFF00FF
  end

  local ArrayStart= math.floor((R2u(addr+0x0E)-256)/4)
  local ArrayCount= R2u(addr+0x40)
  for i= ArrayStart, ArrayStart+ArrayCount-1 do
    AssignmentArrayColors[i]= clr
  end
end

local ObjTbl= {
[0]=NullFn, DoPlyr, NullFn, NullFn, NullFn,
    NullFn, NullFn, NullFn, NullFn, NullFn,
    DoBllt, DoBllt, DoBllt, DoBllt, DoBllt,
    DoBllt, DoBllt, DoBllt, DoBllt, DoBllt,
    DoBllt, DoBllt, DoBllt, DoBllt, DoBllt,
    DoBllt, DoBllt, DoBllt, DoBllt, DoBllt,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr,
    DoOthr, DoOthr, DoOthr, DoOthr, DoOthr
}

--*****************************************************************************
local function ObjList2()
--*****************************************************************************
--Displays some information on objects.
--Well, more like a specific stat.

  Bcount= 0
  Ecount= 0
  local ObjCount= 0
  for i= 0, 59 do
    local addr= 0x1DE4 + 0x74*i
    local X= R4s(addr+0x00)
    local Y= R4s(addr+0x04)
    ObjTbl[i](addr,X,Y)
  end
  PixelTextRight( 9,153,Bcount)
  PixelTextRight(19,153,Ecount)
end
--               _h_H_a+A_H_Aa+h_LaHh_AH_*_A*_+_a
local HeartStr= " h H  +  H   +h   Hh  H      +  "
local AmmoStr = "     a A   Aa    a   A  * A*   a"
local LifeStr = "                L               "
local DirStr  = " < > <>> < ><<> <<>> <> < >> < >"
--*****************************************************************************
local function ItemDrop()
--*****************************************************************************
    gui.pixelText(40,153,HeartStr,0xFFFF8000)
    gui.pixelText(40,153,AmmoStr ,0xFF00C0FF,0)
    gui.pixelText(39,153,LifeStr ,0xFF00FF00,0)
    gui.pixelText(40,146,DirStr  ,0xFFC0C0C0)
    local RNG= R4u(0x17A0)%0x20
    local X= RNG*4 + 40
    gui.drawRectangle(X,153,5,6)
end

local DashDir= {[0]=">","<"}
--*****************************************************************************
local function TimerWatch()
--*****************************************************************************
  if R4s(0x15C0,"IWRAM") ~= 0 then --Dash ready
    gui.pixelText( 24,6,DashDir[R4s(0x15C4)] or "?",0xFFFF80FF)--direction
    PixelTextRight(23,6,        R4s(0x15C0)        ,0xFFFF80FF)--timer
  end

  if R4s(0x15D4,"IWRAM") ~= 0 then --Dashing
    PixelTextRight(32,6,        R4s(0x15D0)        ,0xFF80FF80)--timer
  end

  if R4s(0x1624,"IWRAM") ~= 0 then --Player invincible
    PixelTextRight(40,6,        R4s(0x1628)        ,0xFFFF8000)--timer
  end

  if R4s(0x16B4,"IWRAM") ~= 0 then
    PixelTextRight(60,6,        R4s(0x16B4)        ,0xFF0080FF)--Durability
    PixelTextRight(70,6,        R4s(0x16B8)        ,0xFF0080FF)--Timer
  end
end

local DashFrames= 0
--*****************************************************************************
local function DashCount()
--*****************************************************************************
    if R4s(0x15D4,"IWRAM") ~= 0 then DashFrames= DashFrames+1 end
    PixelTextRight(32,50,DashFrames,0xFF80FF80)    
end

--*****************************************************************************
local function RAMWatch()
--*****************************************************************************
--A convenient way to add important addresses is from the table at the top.

    local Y= 153 - (#RAMList)*7
    for i= 1, #RAMList do
        PixelTextRight(239,Y+i*7,R2s(RAMList[i]))
    end
end

--*****************************************************************************
local function RAMWatch2()
--*****************************************************************************
--A convenient way to add important addresses is from the table at the top.
--Additionally, we can specify method and color. Yay, customization!
--  {a=0x1530,m=R4s,c=0xFF00FFFF}
--a = address ; m = method ; c = color

    local Y= 153 - (#RAMList2)*7
    for i= 1, #RAMList2 do
        local stat= RAMList2[i]
        PixelTextRight(239,Y+i*7,stat.m(stat.a),stat.c)
    end
end

--*****************************************************************************
local function ListVals(ptr,x)
--*****************************************************************************
  local i= 0
  while R2s(ptr,"ROM") ~= -1 do
    gui.pixelText(x   ,i*7,string.format("%04X",R2u(ptr  ,"ROM")))
--    gui.pixelText(x+12,i*7,R1u(ptr+1,"ROM"))
    ptr= ptr+2
    i=i+1; if i > 30 then return end --Just in case
  end
end

--*****************************************************************************
local function FinalHitboxAttempt()
--*****************************************************************************
--If this fails to call forth inspitation, then hitboxes just aren't happening.
--Those addresses just look suspicious, alright?

  local addr= 0x1DE4 + 0x74*1  --Player object

  local index= R2s(addr+0x08,"IWRAM")  --Sprite index
  local ptr=   R4s(addr+0x70,"IWRAM")  --Pointer for object

  if     index == 0 then gui.pixelText(50,0,"Null sprite")  --A guess, really
  elseif ptr   == 0 then gui.pixelText(50,0,"Null pointer") --Not a guess
  else
--I don't actually know if the game uses index as is or subtracts an offset.
--If the numbers are used for hitboxery, I want to know.
    ptr= ptr + (index-1)*4

    ptr= R4s(FetchAddrDomainGBA(ptr))  --Fetching some deeper data
    if (ptr >= 0x08000000) and (ptr < 0x08000000+memory.getmemorydomainsize("ROM")) then
      ptr= ptr - 0x08000000   --Why is this subtraction a requirement? VBA don't need it.
      ListVals(ptr,50)
    else
      gui.pixelText(50,0,"Bad pointer")
    end
  end
end

--*****************************************************************************
local function ProgressColors(v)
--*****************************************************************************
    if v > 0 then return 0xFF00C0FF end --Forward!
    if v < 0 then return 0xFFFFC000 end --Backward!
    return 0xFFFF00FF --We held still
end

--*****************************************************************************
local function ImportantPlayerPixels(PlX,PlY)
--*****************************************************************************
  local PlAir= R4u(0x1554,"IWRAM") == 1
  local PlLeft=R4u(0x1E64,"IWRAM") == 1
  local PlJump=R4u(0x1E6C,"IWRAM")
--  local PlAir= R4u(0x1500,"IWRAM")

--(16,48) Left fall check
  if (not PlAir) or ((PlJump >= 20) and not PlLeft) then
    gui.drawPixel(PlX+16,PlY+48,0xFFFFFFFF)
    gui.drawPixel(PlX+15,PlY+47,0xFFFFFFFF)
    gui.drawPixel(PlX+16,PlY+47,0xFFFFFFFF)
    gui.drawPixel(PlX+17,PlY+47,0xFFFFFFFF)
  end

--(24,48) Right fall check
  if (not PlAir) or ((PlJump >= 20) and PlLeft) then
    gui.drawPixel(PlX+24,PlY+48,0xFFFFFFFF)
    gui.drawPixel(PlX+23,PlY+47,0xFFFFFFFF)
    gui.drawPixel(PlX+24,PlY+47,0xFFFFFFFF)
    gui.drawPixel(PlX+25,PlY+47,0xFFFFFFFF)
  end

--(16, 8) Left head check
  if PlAir and (PlJump < 20) and (not PlLeft) then
    gui.drawPixel(PlX+16,PlY+ 8,0xFFFF80FF)
    gui.drawPixel(PlX+15,PlY+ 9,0xFFFF80FF)
    gui.drawPixel(PlX+16,PlY+ 9,0xFFFF80FF)
    gui.drawPixel(PlX+17,PlY+ 9,0xFFFF80FF)
  end

--(24, 8) Right head check
  if PlAir and (PlJump < 20) and PlLeft then
    gui.drawPixel(PlX+24,PlY+ 8,0xFFFF80FF)
    gui.drawPixel(PlX+23,PlY+ 9,0xFFFF80FF)
    gui.drawPixel(PlX+24,PlY+ 9,0xFFFF80FF)
    gui.drawPixel(PlX+25,PlY+ 9,0xFFFF80FF)
  end

--( 8,47) Left horizontal check
  if PlLeft then
    gui.drawPixel(PlX+ 8,PlY+47,0xFFFFFF00)
    gui.drawPixel(PlX+ 9,PlY+46,0xFFFFFF00)
    gui.drawPixel(PlX+ 9,PlY+47,0xFFFFFF00)
    gui.drawPixel(PlX+ 9,PlY+48,0xFFFFFF00)
  end

--(32,47) Right horizontal check
  if not PlLeft then
    gui.drawPixel(PlX+32,PlY+47,0xFFFFFF00)
    gui.drawPixel(PlX+31,PlY+46,0xFFFFFF00)
    gui.drawPixel(PlX+31,PlY+47,0xFFFFFF00)
    gui.drawPixel(PlX+31,PlY+48,0xFFFFFF00)
  end

--( 8,32) Left walljump check
  if PlAir and (PlJump >= 20) and PlLeft then
    gui.drawPixel(PlX+ 8,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+ 9,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+10,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+ 9,PlY+31,0xFF00FFFF)
    gui.drawPixel(PlX+10,PlY+30,0xFF00FFFF)
  end

--(32,32) Right walljump check
  if PlAir and (PlJump >= 20) and (not PlLeft) then
    gui.drawPixel(PlX+32,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+31,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+30,PlY+32,0xFF00FFFF)
    gui.drawPixel(PlX+31,PlY+31,0xFF00FFFF)
    gui.drawPixel(PlX+30,PlY+30,0xFF00FFFF)
  end

end

--*****************************************************************************
local function ReadAllocationArray()
--*****************************************************************************
  for i= 0, 0xBF do
    local addr= 0x7C44 + i
    local clr= 0xFF000000
    if R1u(addr,"IWRAM") ~= 0 then clr= AssignmentArrayColors[i] end
    gui.drawLine(i,0,i,3,clr)
  end
  gui.drawLine(0xC0,0,0xC0,3,0xFFFFFFFF)
end

local Left,Zero,DamageR,DamageL= 0,0,0,0
local cyan= 0xFF00FFFF
local LastX,LastY= 0,0
--*****************************************************************************
local function BasicHUD()
--*****************************************************************************
--General purpose display function. Stick whatever you like here.

    ReadAllocationArray()

    local CamX,CamY=     R4s(0x1500,"IWRAM"),R4s(0x1504,"IWRAM")
    local PlScrX,PlScrY= R4s(0x1E58,"IWRAM"),R4s(0x1E5C,"IWRAM")

    local PlX,PlY= PlScrX+CamX, PlScrY+CamY

    PixelTextRight(239,  0,R4s(0x1560,"IWRAM"),cyan)
    PixelTextRight(239,  7,PlX)
    PixelTextRight(239, 14,PlX-LastX,ProgressColors(PlX-LastX))

    PixelTextRight(239, 25,R4s(0x1564,"IWRAM"),cyan)
    PixelTextRight(239, 32,PlY)
    PixelTextRight(239, 39,PlY-LastY,ProgressColors(PlY-LastY))

    local BossHP= (R4s(0x1708,"IWRAM")-1)*5 + R4s(0x170C,"IWRAM")
    PixelTextRight(224,153,BossHP)

    ImportantPlayerPixels(PlScrX,PlScrY)

--Piece of code to count our movements for pre-dash horizontal stuff.
    local move= PlX-LastX
    if     move ==  1 then DamageR= DamageR+1
    elseif move ==  0 then Zero= Zero+1
    elseif move == -1 then DamageL= DamageL+1
    elseif move == -2 then Left= Left+1
    end
    PixelTextRight(219,  0,DamageR,0xFFFFFF80)
    PixelTextRight(219,  7,Zero   ,0xFFFFFF00)
    PixelTextRight(219, 14,DamageL,0xFFFFC000)
    PixelTextRight(219, 21,Left   ,0xFFFF4000)

    LastX,LastY= PlX,PlY
end

local Idle= 0
local BossScan
--*****************************************************************************
local function BossRepeat()
--*****************************************************************************
  local inv= R4s(0x16F8,"IWRAM")
  if inv == 0 then
    Idle= Idle+1
  elseif Idle ~= 0 then
    print(string.format("f%d - %d delayed",emu.framecount(),Idle-1))
    Idle= 0
  end
end

--*****************************************************************************
local function BossFirst()
--*****************************************************************************
  local inv= R4s(0x16F8,"IWRAM")
  if inv ~= 0 then
    print(string.format("f%d - First hit",emu.framecount()))
    BossScan= BossRepeat
  end
end

BossScan= BossFirst

--*****************************************************************************
while true do
--*****************************************************************************
--Our overhead.

    ResetColors()
    ObjList2()
    ItemDrop()
    RAMWatch2()
    TimerWatch()
--    DashCount()
    BasicHUD()
--    BossScan()
--    FinalHitboxAttempt()
    emu.frameadvance()
end