local StaticX,StaticY= 60,220
local StaticR= 60
local StaticS= 0x0200
local RotateX,RotateY= 180,220
local RotateR= 60
local RotateS= 0x0200
local RadarColors= {
[0]=0xFFFFFFFF,
0xFF00FF00,
0xFFFFFF00,
0xFF00FFFF,
0xFFFF40FF
}
client.SetGameExtraPadding(0,0,0,120)
local R4u , R4s= memory.read_u32_le , memory.read_s32_le
local R2u , R2s= memory.read_u16_le , memory.read_s16_le
local R1u , R1s= memory.read_u8 , memory.read_s8
local function FetchAddrDomainGBA(a)
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(string.format("Unknown address %08X", a),1)
end
end
local function WordToAngle(v)
return -(v/32768)*math.pi
end
local function PartialFillTable(T,x,y,r,s)
T.x= x; T.y= y; T.r= r; T.s= s
T.Left= x-r; T.Top= y-r; T.Right= x+r; T.Bottom= y+r
end
local function FillTable(T,x,y,r,s,pl)
T= T or {}
T.x= x; T.y= y; T.r= r; T.s= s; T.pl= pl
T.Left= x-r; T.Top= y-r; T.Right= x+r; T.Bottom= y+r
local a= 0x12D60 + pl*0xCC
T.Addr= a
T.PlX= R4s(a+0x00,"EWRAM")
T.PlY= R4s(a+0x04,"EWRAM")
local Facing= R2u(a+0x78,"EWRAM")
T.Facing= Facing
Facing= WordToAngle(Facing)
T.AngleF= Facing
T.Sine= math.sin(Facing); T.Cosine= math.cos(Facing)
return T
end
local function InBounds(T,x,y)
return (x >= T.Left) and (x <= T.Right) and (y >= T.Top) and (y <= T.Bottom)
end
local function GridUnderlayS(sT)
local range= (sT.r+0.5) * sT.s
local Vline= (math.ceil((sT.PlX - range)/0x4000)*0x4000 - sT.PlX) / sT.s + sT.x
while Vline <= sT.Right do
gui.drawLine(Vline,sT.Top,Vline,sT.Bottom,0xFF404040)
Vline= Vline + 0x4000/sT.s
end
local Hline= (math.ceil((sT.PlY - range)/0x4000)*0x4000 - sT.PlY) / sT.s + sT.y
while Hline <= sT.Bottom do
gui.drawLine(sT.Left,Hline,sT.Right,Hline,0xFF404040)
Hline= Hline + 0x4000/sT.s
end
end
local function MomentumCompass(sT)
local z= WordToAngle(R2s(sT.Addr+0x78,"EWRAM"))
local x= sT.x + sT.r*math.cos(z)
local y= sT.y - sT.r*math.sin(z)
gui.drawLine(sT.x, sT.y,x,y,0xFFFF00FF)
z= WordToAngle(R2s(sT.Addr+0x7A,"EWRAM"))
x= sT.x + sT.r*math.cos(z)
y= sT.y - sT.r*math.sin(z)
gui.drawLine(sT.x, sT.y,x,y,0xFF00FF00)
end
local function RivalRadarNorth(sT)
local OriginX,OriginY= sT.PlX,sT.PlY
for i= 0, 4 do
local a= 0x12D60 + i*0xCC
local MachineX,MachineY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
if (R1s(a+0xB6,"EWRAM") ~= -1) then
local X= math.floor((MachineX-OriginX)/sT.s+0.5) + sT.x
local Y= math.floor((MachineY-OriginY)/sT.s+0.5) + sT.y
if InBounds(sT , X,Y) then
local clr= RadarColors[i] or 0xFFC0C0C0
gui.drawLine(X-4,Y ,X+4,Y ,clr)
gui.drawLine(X ,Y-4,X ,Y+4,clr)
end
end
end
end
local function GridUnderlayR(rT)
end
local function MomentumAngle(rT)
local a= rT.Addr
local Facing= R2u(a+0x78,"EWRAM")
local Momentum= R2u(a+0x7A,"EWRAM")
local Diff= (Facing - Momentum + 0x8000)%0x10000 - 0x8000
local Angle= WordToAngle(Facing)
local HalfR= rT.r/2
local x= rT.x - HalfR*math.cos(Angle)
local y= rT.y - HalfR*math.sin(Angle)
gui.drawLine(x-1,y ,x+1,y ,0xFF808080)
gui.drawLine(x ,y-1,x ,y+1,0xFF808080)
Angle= WordToAngle(Diff)
x= rT.x + rT.r*math.sin(Angle)
y= rT.y - rT.r*math.cos(Angle)
gui.drawLine(rT.x,rT.y,x,y,0xFF00FF00)
end
local function RivalRadarFacing(rT)
local OriginX,OriginY= rT.PlX, rT.PlY
local Sine= rT.Sine
local Cosine= rT.Cosine
for i= 0, 4 do
local a= 0x12D60 + i*0xCC
local MachineX,MachineY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
if (R1s(a+0xB6,"EWRAM") ~= -1) then
local X,Y= MachineX-OriginX,MachineY-OriginY
X,Y= Sine*X+Cosine*Y, -Cosine*X+Sine*Y
X= math.floor(X/rT.s+0.5) + rT.x
Y= math.floor(Y/rT.s+0.5) + rT.y
if InBounds(rT , X,Y) then
local clr= RadarColors[i] or 0xFFC0C0C0
gui.drawLine(X-4,Y ,X+4,Y ,clr)
gui.drawLine(X ,Y-4,X ,Y+4,clr)
end
end
end
end
local function MachineHUD(n)
local a= 0x12D60 + n*0xCC
local x, y= R4s(a+0x00,"EWRAM"), R4s(a+0x04,"EWRAM")
local Facing, Momentum= R2u(a+0x78,"EWRAM"), R2u(a+0x7A,"EWRAM")
gui.pixelText( 0, 0,string.format("%8X",x))
gui.pixelText( 0, 7,string.format("%8X",y))
gui.pixelText( 0, 16,string.format("%8X",R4s(a+0x74,"EWRAM")))
x= x - R4s(a+0x08,"EWRAM")
y= y - R4s(a+0x0C,"EWRAM")
local v= math.floor(math.sqrt(x*x + y*y))
gui.pixelText( 0, 23,string.format("%8X",v),0xFF00FFFF)
gui.pixelText( 0,160,string.format("%4X",Facing) ,0xFFFF00FF)
gui.pixelText( 0,167,string.format("%4X",Momentum),0xFF00FF00)
v= (Facing - Momentum + 0x8000)%0x10000 - 0x8000
local clr= 0xFFFF00FF
if v > 0 then clr= 0xFFFFFF00 end
if v < 0 then clr= 0xFF00FFFF end
gui.pixelText( 0,174,string.format("%4X",math.abs(v)),clr)
gui.pixelText(224, 0,string.format("%4X",R2u(a+0x8A,"EWRAM")))
gui.pixelText(224, 7,string.format("%4d",R1u(a+0xA2,"EWRAM")))
gui.pixelText(224,153,string.format("%4d",R2u(a+0x8C,"EWRAM")))
gui.pixelText(224,145,string.format("%4d",R1u(a+0xA1,"EWRAM")))
end
local function BasicHUD()
for i= 0, 4 do
local addr= 0x12D60 + 0xCC*i
local v= R1s(addr+0xB6,"EWRAM")
local clr= RadarColors[i]
if v == -1 then clr= 0xFFA0A0A0 end
gui.pixelText(231,160+7*i,string.format("%2d",v),clr)
end
end
local function StaticHUD(sT)
GridUnderlayS(sT)
MomentumCompass(sT)
RivalRadarNorth(sT)
end
local function RotatingHUD(rT)
GridUnderlayR(rT)
MomentumAngle(rT)
RivalRadarFacing(rT)
end
local StatsTbl= {}
while true do
local Player= R1u(0x2B63,"IWRAM")
if Player < 5 then
FillTable( StatsTbl,StaticX,StaticY,StaticR,StaticS,Player)
StaticHUD(StatsTbl)
PartialFillTable(StatsTbl,RotateX,RotateY,RotateR,RotateS)
RotatingHUD(StatsTbl)
MachineHUD(Player)
end
BasicHUD()
emu.frameadvance()
end