User File #38507979558876140

Upload All User Files

#38507979558876140 - Zook Man ZX4 - Just a plain frame counting script.

ZM_SegmentCounter.lua
740 downloads
Uploaded 4/22/2017 4:48 AM by FatRatKnight (see all 245)
Intent of the script is to state how many frames it took to complete the immediate segment, as well as how long it takes to do the stage. The state machine in it insists that it sees the beginning of a stage before it starts doing its counting. Hopefully, this will make comparisons easier. If anyone has ideas on better measurement points, I don't mind suggestions.
I've commented out a piece of code, around line 145, that would report how many frames you spent traveling at each pixel/frame. The script is keeping track, just that it won't print the actual stuff without that stuff I commented out. It's cleaner without it, but if you want the added information, go find that spot.
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 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 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,method)
--*****************************************************************************
--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


--*****************************************************************************
local function FetchPosition()
--*****************************************************************************
  local X= R4s(0x14F0) + R4s(0x1E58)  --Cam and screen position, respectively
  local Y= R4s(0x14F4) + R4s(0x1E5C)  --Yeppers.

  return X,Y
end

--*****************************************************************************
local function RecordMovement(T,v)
--*****************************************************************************
    local diff= v - T.Last
    diff= (diff+128)%256 - 128  --Arbitrarily trim within one signed byte
    T[diff]= (T[diff] or 0) + 1
    T.Last= v                   --Our new recorded position.
end

--*****************************************************************************
local function ResetMovements(T)
--*****************************************************************************
--Has a side-effect of nuking my last position, too.

  for k,v in pairs(T) do
    if type(v) == "number" then T[k]= nil end
  end
end

--*****************************************************************************
local function ReadMovements(T)
--*****************************************************************************
  local s= ""
  for k,v in pairs(T) do
    if (type(v) == "number") and (type(k) == "number") then
      s= string.format("%s| %d:%d ",s,k,v)
    end
  end
  return s .. "|"
end

--Might want a constructor function...
local MovedX= {Rec=RecordMovement, Reset=ResetMovements, Read=ReadMovements}
local MovedY= {Rec=RecordMovement, Reset=ResetMovements, Read=ReadMovements}

local StateMachine, AwaitIntro, BeginStage, StageWatch
local fc_StageBegin, fc_SegmentBegin= 0,0
local v_CurrentSegment= 0

--*****************************************************************************
AwaitIntro= function()
--*****************************************************************************
--Just waits for that beam-in state.

  if R4s(0x15F0) ~= 1 then return end  --Insist on the beam-in lock
  StateMachine= BeginStage
--... And do nothing else
end

--*****************************************************************************
BeginStage= function()
--*****************************************************************************
  if R4s(0x15F0) == 1 then return end  --Insist the beam-in goes away
  StateMachine= StageWatch

  MovedX:Reset()
  MovedY:Reset()
  MovedX.Last,MovedY.Last= FetchPosition()

  local cf= emu.framecount()
  fc_StageBegin, fc_SegmentBegin= cf, cf
  v_CurrentSegment= R4s(0x1530)
  print(string.format("f%05d *** STAGE %d ***",
    cf,
    R4s(0x152C)
  ))
end

--*****************************************************************************
local function HandleBeamOut()
--*****************************************************************************
  StateMachine= AwaitIntro

  local cf= emu.framecount()
  print(string.format("f%05d Segment%2d:%4d",
    cf,                    --Current frame
    v_CurrentSegment,      --What segment we're on
    cf - fc_SegmentBegin   --Diff of current frame and when segment began
  ))
--I'm not going to spill our movement information here.
--All such cases where we beam out is in a stationary room anyway.

  print(string.format("=== END OF STAGE %d (Frames: %d) ===",
    R4s(0x152C),
    cf - fc_StageBegin
  ))
end

--*****************************************************************************
local function HandleNewSeg()
--*****************************************************************************
  local cf= emu.framecount()
  print(string.format("f%05d Segment%2d:%4d",
    cf,                    --Current frame
    v_CurrentSegment,      --What segment we're on
    cf - fc_SegmentBegin   --Diff of current frame and when segment began
  ))
--[[
  print(string.format("(X)>%s###(Y)>%s",
    MovedX:Read(),MovedY:Read()
  ))
]]--

  v_CurrentSegment= R4s(0x1530)
  fc_SegmentBegin= cf
  MovedX:Reset()
  MovedY:Reset()
  MovedX.Last,MovedY.Last= FetchPosition()
end

--*****************************************************************************
local function HandleFrame()
--*****************************************************************************
  local x,y= FetchPosition()
  MovedX:Rec(x)
  MovedY:Rec(y)
end

--*****************************************************************************
StageWatch= function()
--*****************************************************************************
  HandleFrame()
  if     R4s(0x15F0) == 11 then HandleBeamOut()              --Check beam-out
  elseif R4s(0x1530) ~= v_CurrentSegment then HandleNewSeg() --Check segment
  end
end

StateMachine= AwaitIntro
--*****************************************************************************
while true do
--*****************************************************************************
--Our overhead.

    StateMachine()
    emu.frameadvance()
end