User File #60949290389503023

Upload All User Files

#60949290389503023 - HUD display for The Adventures of Batman and Robin v4

TheAdventuresOfBatmanAndRobin+.lua
487 downloads
Uploaded 1/27/2020 8:26 PM by Truncated (see all 22)
Actually there is no version number but the file's latest change was 2017-01-19. I don't remember what was changed, but it's three years better/newer than previous upload.
-- The Adventures of Batman and Robin
-- 2013-2016, feos and r57shell

-- GLOBALS --
MsgTable  = {}
MsgTime   = 30
MsgOffs   = 16
MsgCutoff = 60
RNGcount  = 0
SpawnCount= 0
SpawnOpac = 192
SpawnX    = 0
SpawnY    = 0
Enemies   = 0
Items     = 0
Hearts    = 0

-- SHORTCUTS --
rb  = memory.readbyte
rbs = memory.readbytesigned
rw  = memory.readword
rws = memory.readwordsigned
rl  = memory.readlong
rls = memory.readlongsigned
rex = memory.registerexec
getr= memory.getregister

function GetCam()
	xcam = rws(0xFFDFC4)
	if rb(0xFFFFF6) == 50 then
		ycam= rws(0xFFDFE0)-20
	else
		ycam = 0
	end
end

function EnemyPos(Base)
	GetCam()
	x1 = rws(Base + 0x12) - xcam
	y1 = rws(Base + 0x14) - ycam
	x2 = rws(Base + 0x16) - xcam
	y2 = rws(Base + 0x18) - ycam
	hp = rws(Base + 0x1E)
end

function PlayerPos()
	local sbase1 = rw(0xFFAD5C) + 0xFF0000
	local sbase2 = rw(0xFFADB6) + 0xFF0000
	p1speedx = rls(sbase1 + 0x18) / 0x10000
	p1speedy = rls(sbase1 + 0x1C) / 0x10000
	p2speedx = rls(sbase2 + 0x18) / 0x10000
	p2speedy = rls(sbase2 + 0x1C) / 0x10000
  	LIFT = memory.readword(0xFF9024)
end

function HandleMsgTable(clear)
	for i = 1, #MsgTable do
		if (clear) then
			MsgTable[i] = nil
		end		
		if (MsgTable[i]) then
			GetCam()
			if (MsgTable[i].y_ > MsgCutoff) then
				MsgY1 = 0
				MsgY2 = 6
			else
				MsgY1 = 203
				MsgY2 = 203				
			end
			local opacity = AND((MsgTable[i].timer_ - gens.framecount() + 2)*7, 0xFF)
			gui.line(i * MsgOffs + 3, MsgY2, MsgTable[i].x_ - xcam, MsgTable[i].y_, 0xFF000000+opacity)
			gui.text(i * MsgOffs    , MsgY1, MsgTable[i].damage_, "red")
			if (MsgTable[i].timer_ < gens.framecount()) then
				MsgTable[i] = nil
			end
		end
	end
end

function HandleDamage()
	local damage = AND(getr("d0"),   0xFFFF)
	local base   = AND(getr("a2"), 0xFFFFFF)	
	EnemyPos(base)
	unit = {
		timer_ = gens.framecount() + MsgTime,
		damage_ = damage,
		x_ = x1 + xcam,
		y_ = y1
	}
	for i = 1, 200 do
		if MsgTable[i] == nil then
			MsgTable[i] = unit
			break
		end
	end
end

function Collision()
	GetCam()
	local a0 = AND(getr("a0"), 0xFFFFFF)
	local a6 = AND(getr("a6"), 0xFFFFFF)
	local damage = rw(a6 + 0x12)
	local id  = rw(a6 + 2)
	local wx2 = getr("d6") - xcam
	local wy2 = getr("d7") - ycam
	local wx1 = getr("d4") - xcam
	local wy1 = getr("d5") - ycam
--	gui.text(wx2 + 2, wy1 + 1, string.format("%X",a6))
	if (damage == 0) then
		damage = rw(a0 + 0x34)
	end
	if (DamageHitbox) then
		gui.box(wx1, wy1, wx2, wy2, "#FF000000")
		gui.text(wx1 + 2, wy1 + 1, damage)
	else
		gui.box(wx1, wy1, wx2, wy2, "#FFFF0000")
		if id == 0x53B4 then Hearts = Hearts + 1 end
	end
end

function InRange(var, num1, num2)
	if (var >=  num1) and (var <= num2)
	then return true
	end
end

function Item()
	GetCam()
	local a6   = AND(getr("a6"), 0xFFFFFF)
	local x    = rw(a6 + 0x3E) - xcam
	local y    = rw(a6 + 0x42)
	local code = rb(a6 + 0x19)
	if     InRange(code,  0,  1) then return
	elseif InRange(code,  7, 19) then item = "Amo" -- ammo
	elseif InRange(code, 21, 23) then item = "Cha" -- fast charge
	elseif InRange(code, 24, 26) then item = "Bom" -- bomb
	elseif InRange(code, 27, 29) then item = "Lif" -- life
	elseif InRange(code, 30, 47) then item = "HiP" -- hearts
	else                              item = tostring(code)
	end
	gui.text(x-7, y, string.format("%s"  , item   ), "yellow")
--	gui.text(x-7, y, string.format("\n%X", a6+0x19), "yellow")
end

function Hitbox(address)
	local i = 0
	local base = rw(address)	
	while (base ~= 0) do
		base = base + 0xFF0000
		if (rw(base + 2) == 0) then break end
		EnemyPos(base)
		if (address == 0xFFDEB2) then
			gui.box(x1, y1, x2, y2, "#00FF0000")
		elseif (address == 0xFFDEBA) then
			gui.box(x1, y1, x2, y2, "#00FFFF00")
			gui.text(x1 + 2, y1 + 1, hp, "#FF00FF")
		--	if (x2 <    0) then gui.text(x1 + 2, y2 - 7, "x:" .. x1      ) end
		--	if (x1 >= 320) then gui.text(x1 + 2, y2 - 7, "x:" .. x1 - 320) end
		--	if (y2 <    0) then gui.text(x2 + 2, y2 - 7, "y:" .. y2      ) end
			local offtext = ""
			if (x2 <    0) then offtext = offtext .. "x:" .. x1       end
			if (x1 >= 320) then offtext = offtext .. "x:" .. x1 - 320 end
			if (y2 <    0) then offtext = offtext .. "y:" .. y2       end
			if (y2 >= 224) then offtext = offtext .. "y:" .. y2 - 224 end
			if offtext ~= "" then
				gui.text(x1 + 2, y2 - 7, offtext)
			end
		end
		base = rw(base + 2)
		i = i + 1
		if (i > 400) then break end
	end
end

function Objects()
	if rb(0xFFFFF6) ~= 50 then return end
	Enemies = 0
	Items   = 0
	GetCam()
	local base = 0xFFAD54
	for i=0,100 do
		local link = rw (base+   6)
		local ptr1 = rw (base+0x0A)+0xFF0000
		local x    = rws(base+0x3E)
		local xsub = rb (base+0x40)
		local y    = rws(base+0x42)
		local ysub = rb (base+0x44)
		local hp   = rw (base+0x52)
		local ptr2 = rl (ptr1+0x2A)
		local code = rw (ptr2)
		if base > 0 then
			if ptr2 == 0x27DEE -- helicopter black
			or ptr2 == 0x27F9C -- helicopter red
			or ptr2 == 0x2804E -- plane black
			or ptr2 == 0x28134 -- helicopter green
			or ptr2 == 0x282B8 -- plane red
			or ptr2 == 0x2860A -- missile
			or ptr2 == 0x28DD2 -- helicopter red phase 1
			or ptr2 == 0x28E08 -- helicopter red phase 2
			then
				Enemies = Enemies + 1
			elseif ptr2 == 0x13326
			or     ptr2 == 0x13BDE
			then
				Items = Items + 1
			else
			--	gui.text(x - xcam, y - ycam, string.format("%X", ptr2), "green")
			end
		end
		base = link + 0xFF0000
		local a5   = rl (base)
		if a5 == 0x88BE then return end
	end
end

function Spawns()
	if rb(0xFFFFF6) ~= 50 then return end
	local base = AND(getr("a6"), 0xFFFFFF)
	local ptr1 = rw(base+0x0A) + 0xFF0000
	local ptr2 = rl(ptr1+0x2A)
	local code = rw(ptr2)
	SpawnX = rws(base+0x3E) - xcam
	SpawnY = rws(base+0x42) - ycam
	if  code ~= 0xAE6  -- drone
	and code ~= 0xAF2  -- mini-missile
	and code ~= 0x2384 -- item
	then
		SpawnOpac  = 192
		SpawnCount = SpawnCount + 1
	end
end

function Main()
	local color0  = "yellow"
	local color1  = "yellow"
	local color2  = "yellow"
	local base1   = 0xFFAD54
	local base2   = 0xFFADAE
--	local hp1     = rw (0xFFF654)
--	local life1   = rw (0xFFF644)
	local X1      = rw (base1 + 0x3E)
	local X1sub   = rb (base1 + 0x40)
	local Y1      = rws(base1 + 0x42)
	local Y1sub   = rb (base1 + 0x44)
	local X2      = rw (base2 + 0x3E)
	local X2sub   = rb (base2 + 0x40)
	local Y2      = rws(base2 + 0x42)
	local Y2sub   = rb (base2 + 0x44)
	local RNG1    = rw (0xFFF5FC)
--	local RNG2    = rl (0xFFF5FE)
	local Weapon1 = rb (0xFFF67B)
	local Weapon2 = rb (0xFFF6BB)
	local Charge1 = (rw(0xFFF658) - 0x2800) / -0x80
	local Charge2 = (rw(0xFFF698) - 0x2800) / -0x80
	local ScreenLock = rw(0xFFDFC0)
	if Charge1 <= 0 then Charge1 = 0; color1 = "red" end
	if Charge2 <= 0 then Charge2 = 0; color2 = "red" end
	if RNGcount > 1 then              color0 = "red" end
	HandleMsgTable()
	PlayerPos()
	Objects()
	if rb(0xFFFFF6) == 50 then
		gui.line( 34,  42, SpawnX, SpawnY, 0x00FF0000+ SpawnOpac)
		gui.text(  4,  35, string.format("Obj: %d"   , SpawnCount),"green")
		gui.text(  4,  43, string.format("%d %d %d"  , Enemies, Items, Hearts/2))
	end
	gui.text(  1, 210, string.format("\nRNG:%X"  , RNG1))
	gui.text( 40, 210, string.format("\nLock:%d" , ScreenLock))
	gui.text( 34, 210, string.format("\n%d"      , RNGcount),   color0)
	gui.text( 80,  20, string.format("%2d"       , Charge1),    color1)
	gui.text(235,  20, string.format("%2d"       , Charge2),    color2)
	gui.text(180, 210, string.format("\n%2d"     , Weapon1+1), "yellow")
	gui.text(300, 210, string.format("\n%2d"     , Weapon2+1), "yellow")
	gui.text( 81, 210, string.format("Pos: %d.%d\nSpd: %.5f", X1, X1sub, p1speedx), "#AAAAAA")
	gui.text(137, 210, string.format("/ %d.%d\n/ %.5f"      , Y1, Y1sub, p1speedy), "#AAAAAA")
	gui.text(203, 210, string.format("Pos: %d.%d\nSpd: %.5f", X2, X2sub, p2speedx), "#00BB00")
	gui.text(260, 210, string.format("/ %d.%d\n/ %.5f"      , Y2, Y2sub, p2speedy), "#00BB00")
	Hitbox(0xFFDEB2)
	Hitbox(0xFFDEBA)
	RNGcount  = 0

	if rb(0xFF4633) == 5 then	
		gui.text(143,3,string.format("     %2d", LIFT), 0xFFFF00FF, clear) 
	end
	
	DER =  memory.readword(0xFFAEA0)
	gui.text(135,3,string.format("     %2d", DER), 0xFFFF00FF, clear)
end

emu.registerafter(function()
	SpawnOpac = SpawnOpac - 4
	if SpawnOpac < 0 then SpawnOpac = 0 end
end)

emu.registerbefore(function()
	Hearts = 0
end)

savestate.registerload(function()
	SpawnCount = 0
	SpawnOpac  = 192
	Enemies    = 0
	Items      = 0
	Hearts     = 0
	return HandleMsgTable(1)
end)

gui.register(Main)
rex(0x375A,  function() DamageHitbox = false end)
rex(0x375E,  function() DamageHitbox = true  end)
rex(0x3768,  function() DamageHitbox = false end)
rex(0x376C,  function() DamageHitbox = true  end)
rex(0x65C4,  function() DamageHitbox = false end)
rex(0x65C8,  function() DamageHitbox = true  end)
rex(0x995C,  function() RNGcount = RNGcount + 1 end)
rex(0x4738,  Item)
rex(0x4534,  Item)
rex(0x8DE6,  Spawns)
rex(0x8DCE,  Spawns)
rex(0x8C9A,  Collision)
rex(0x1085A, HandleDamage) -- meelee
rex(0x10CBA, HandleDamage) -- weapon
rex(0x10CC4, HandleDamage) -- weapon