User File #12283335305507377

Upload All User Files

#12283335305507377 - SNES Soul Blazer script v2 (lsnes)

SB_General_v2.lua
1169 downloads
Uploaded 1/27/2014 3:57 AM by FatRatKnight (see all 245)
Cleaned up a few things in code. Also, it displays hitboxes! Well, green rectangles of some sort. Not entirely sure if they are hitboxes, but it seems to be so for most things. The player's rectangle isn't a hitbox, it seems.
Still gets the same false positives for lair information. Aside from added boxes and some code cleaning for (hopefully) easier maintenance, it's largely the same as the previous script.
--Soul Blazer / Soul Blader script. By FatRatKnight

local Region= "J" -- Try "U" or "J" - Perhaps I should code an auto-identify

local R1u,R1s= memory.readbyte ,memory.readsbyte
local R2u,R2s= memory.readword ,memory.readsword
local R4u,R4s= memory.readdword,memory.readsdword
local function NullFn() end

local obj_list_cr= {}

--*****************************************************************************
local function Roll(rTbl)
--*****************************************************************************
    local c= 0
    for i= 14, 0, -1 do
        local v= rTbl[i]+rTbl[i+1]+c
        c= math.floor(v/0x100)
        rTbl[i]= v%0x100
    end
    rTbl[15]= (rTbl[15]+1)%0x100
end

local R= {}
local Rlist= {0} -- Have a default to display without an error.

local Thresholds= {
[0]= {L= 1, M= 4},
     {L= 3, M= 8},
     {L= 5, M=12},
     {L= 7, M=16},
     {L= 9, M=20},
     {L=11, M=24},
     {L=51, M=100},
}
--*****************************************************************************
local function GetColor(v,zone)
--*****************************************************************************
    if zone > 7 then return 0x808080 end -- I'm confused.
    if v < Thresholds[zone].L then return 0x00FFFF end  -- Large. Awesome.
    if v < Thresholds[zone].M then return 0xFFFF00 end  -- Medium. Nice.
    return 0x808080 -- Small. Nuts.
end

local OldR= -1
--*****************************************************************************
local function UpdateRNG(count)
--*****************************************************************************
    local TestR= R4u(0x7E0302)
    if TestR == OldR then return end -- Assume we're good, don't process.
    OldR= TestR

    for i= 0,15 do R[i]= R1u(0x7E0302+i) end
    for i= 1, count do
        Roll(R)
        Rlist[i]= R[0]
    end
end

local DirTbl= {[0]="^","v",">","<"}
--*****************************************************************************
local function RNGHandler(x,top,count)
--*****************************************************************************
    UpdateRNG(count)
    for i= 1, count do
        local c= GetColor(Rlist[i]%100,R1u(0x7E03BA))
        gui.text(x   ,top + 15*(i-1), string.format("%3d",Rlist[i]), c)
        gui.text(x+24,top + 15*(i-1), DirTbl[Rlist[i]%4])
    end
end



local DisplayBoxes= {}
--*****************************************************************************
local function ShowObjectBoxes(SX,SY)
--*****************************************************************************
    if #DisplayBoxes <= 0 then return end

    for i= 1, #DisplayBoxes do
        local bx= DisplayBoxes[i]

        gui.rectangle(
             bx.L   *SX  , bx.T   *SY  ,
--           bx.R   *SX  , bx.B   *SY  ,
            (bx.R+1)*SX-1,(bx.B+1)*SY-1,
            1,0x4000FF00,0xE000FF00
        )
    end
end

local CamRegion= {U= 0x7E0052, J= 0x7E0050}
local CamAddr= CamRegion[Region]
--*****************************************************************************
local function MakeObjectBox_cr(obj)  -- Coroutine function
--*****************************************************************************
--Grabs box data for later painting.

    local BoxesToPaint= 0
    local CamX, CamY= R2s(CamAddr)+16,R2s(CamAddr+2)+16
    while obj do
        if R2u(obj+0x16) < 0x8000 then -- Luckily the top bit says visibility
            BoxesToPaint= BoxesToPaint+1

            local b= DisplayBoxes[i] or {} -- I'm silly, reusing tables

-- Get every side of our box!
            local X,Y= R2s(obj+0x00)-CamX, R2s(obj+0x02)-CamY
            b.L,b.T= X-R2s(obj+0x08)     , Y-R2s(obj+0x0A)
            b.R,b.B= X+R2s(obj+0x0C)-b.L , Y+R2s(obj+0x0E)-b.T

            X= b.L
            Y= b.T
            b.L= math.max(0,math.min(255    ,b.L))
            b.T= math.max(0,math.min(223    ,b.T))

            X= b.L-X -- I want to know whether my range restriction
            Y= b.T-Y -- actually caused a change I need to know.
            b.R= math.max(0,math.min(255-b.L,b.R-X))
            b.B= math.max(0,math.min(223-b.T,b.B-Y))

--Color. I don't know how to identify objects, but once I do, I'll love colors!
            b.c= 0x00FF00

--Well, store the information.
            DisplayBoxes[BoxesToPaint]=b
        end
        obj= coroutine.yield()
    end

--Shrink down our list if what we have now is less than before.
    while DisplayBoxes[BoxesToPaint+1] ~= nil do
        BoxesToPaint= BoxesToPaint+1
        DisplayBoxes[BoxesToPaint]= nil
    end
end
table.insert(obj_list_cr,MakeObjectBox_cr)



local LairData= {n=0,t=0}
local LairColors= {}
--*****************************************************************************
local function ShowLairs(x,top)
--*****************************************************************************
    local lairs= LairData.n
    gui.text(x   ,top+lairs*15,string.format("%3d",lairs     ),0x00FFFF)
    gui.text(x+40,top+lairs*15,string.format("%3d",LairData.t),0xFFFF00)

    if LairData.n <= 0 then return end
    for i= 1, LairData.n do
        gui.text(x,top+(i-1)*15,LairData[i],LairColors[i])
    end
end

--*****************************************************************************
local function LairList_cr(obj) -- coroutine function
--*****************************************************************************
-- Attempts to identify and store a list of lairs for later painting

    local lairs= 0
    local total= 0
    while obj do
        total= total+1 -- Total object count. Just in case.

--Identify if this is a lair.
--Method gives several false positives, minimal false negatives. Need better.
        local count= R1u(obj+0x2E) -- Count of enemies left
        local Assoc= R2u(obj+0x32) -- Associated lair
        if (count ~= 0) and (Assoc == 0) then
            lairs= lairs+1  -- Lairs counted.

-- In sight, or not?
            local color= 0x00FF00
            if R2u(obj+0x16) >= 0x8000 then color= 0x7F7F7F end
            LairColors[lairs]= color

-- Stick the text in place
            LairData[lairs]= string.format("%3X %3X %2d %3d",
                R2u(obj),R2u(obj+2),count,R2u(obj+0x14)
            )
        end

        obj= coroutine.yield()
    end

    LairData.n= lairs -- Our display routine will use this n.
    LairData.t= total -- Would like to see how many objects total.
end
table.insert(obj_list_cr,LairList_cr)

--*****************************************************************************
local function Finalize(FnTbl)  for i= 1, #FnTbl do FnTbl[i]() end  end
--*****************************************************************************

local ObjectHeaderPointer= {U= 0x7E06A6, J= 0x7E06A3}
local ObjPtr= ObjectHeaderPointer[Region]
--*****************************************************************************
local function IterateObjects()
--*****************************************************************************
    if #obj_list_cr <= 0 then return end -- Uh, nothing to do. Defensive code

    local co= {}
    for i= 1, #obj_list_cr do co[i]= coroutine.wrap(obj_list_cr[i]) end
    local Panic= 0
    local Next= R2u(ObjPtr)
    while Next ~= 0 do
        Panic= Panic+1
        if Panic > 70 then -- There shouldn't be more than 64 objects anyway.
            gui.status("SB_obj","PANIC")
            Finalize(co)
            return
        end

        local Addr= 0x7E0000 + Next

        for i= 1, #co do co[i](Addr) end -- Feed our functions objects!

        Next= R2u(Addr + 0x3E)
    end
    gui.status("SB_obj",Panic) -- A number indicates normal function.
    Finalize(co)
end

local OldEmulated= on_frame_emulated or NullFn
on_frame_emulated= function() OldEmulated(); IterateObjects() end
local OldLoad= on_post_load or NullFn
on_post_load= function(s,b) OldLoad(s,b); IterateObjects() end

local RNG_count,RNG_prev= 0, 0
--*****************************************************************************
local function BasicHUD(x,top,height)
--*****************************************************************************
    gui.text(0, 0,string.format("%4X",R2u(0x7E0800)),0xFFFF80,0x40000000)
    gui.text(0,15,string.format("%4X",R2u(0x7E0802)),0x80FFFF,0x40000000)

    local bottom= top+height

    gui.text(x,bottom-16,string.format("%4X",R2u(0x7E0312)))


    local RNG= R1u(0x7E0311)
    local RNG_diff= (RNG - RNG_prev) % 256
    RNG_count= RNG_count + RNG_diff
    RNG_prev= RNG
    gui.text(x,bottom-32,string.format("%5d:%2X",RNG_count,RNG_prev))


end


local OldPaint= on_paint or NullFn -- Script chaining!

--*****************************************************************************
function on_paint(non_synth)
--*****************************************************************************
    OldPaint(non_synth) -- Decent way to chain scripts together.

    local x,height= gui.resolution()
    local ScaleX, ScaleY= x/256, height/224
    x= x+gui.delta_right_gap(152)  -- Place ourselves to the right of that gunk

    local y= gui.delta_top_gap(0) -- Incorperate spare space provided by the
    height= height+y+gui.delta_bottom_gap(0) -- chained scripts we have.
    local count= math.floor(height/15)

    RNGHandler(x,-y,count)
    ShowLairs(x+40,-y)
    ShowObjectBoxes(ScaleX,ScaleY)
    BasicHUD(x+40,-y,height)
end


--[[
Address 0x7E0800, object size=64
+0x00,2s X-pos
+0x02,2s Y-pos
+0x04,2s X-spd
+0x06,2s Y-spd
+0x08,2s Hitbox Left (subtract from X-pos)
+0x0A,2s Hitbox Top  (subtract from Y-pos)
+0x0C,2s Hitbox Right   (add to X-pos)
+0x0E,2s Hitbox Bottom  (add to Y-pos)
+0x10,
+0x12,
+0x14,2u Useful timer (such as lair spawn rate)
+0x16,2x Flags (0x8000 indicates offscreen)
+0x18,2x Some kind of ID number?
+0x1A,
+0x1C,
+0x1E,
+0x20,
+0x22,
+0x24,
+0x26,2s Invincibility timer
+0x28,
+0x2A,
+0x2C,
+0x2E,2x Looks suspicious... Count in lair?
+0x30,
+0x32,2x Link to associated lair
+0x34,
+0x36,
+0x38,
+0x3A,
+0x3C,2x Link (prev)
+0x3E,2x Link (next)
]]--