--GBA F-Zero: Maximum Velocity - General script
--Intent is essentially an on-screen info dump.
--For use with BizHawk
--FatRatKnight
--Setup
local CompassX,CompassY= 60,220 --Position for compass center
local CompassR= 60 --Radius, in pixels, for compass
local RadarX,RadarY= 180,220 --Position for radar center
local RadarR= 60 --Range, in pixels, for radar
local RadarZ= 0x0200 --Distance each pixel represents
client.SetGameExtraPadding(0,0,0,120) -- Yay, bottom border
--##############################################################################
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 ROMmin,ROMmax= 0x08000000, 0x08000000+memory.getmemorydomainsize("ROM")
--*****************************************************************************
local function FetchAddrDomainGBA(a)
--*****************************************************************************
--Stand-in for System Bus. Highly desired when you got a full pointer.
--I don't know all regions, though.
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)
--*****************************************************************************
-- Input: Angle in 1/65536 of a revolution per unit
-- Output: Angle in radians
return (v/32768)*math.pi
end
--*****************************************************************************
local function CompassHUD(n) --Input: Who is player?
--*****************************************************************************
-- Displays lines. This is to give a visual on momentum and facing.
local a= 0x12D60 + n*0xCC --02012D60, a region in EWRAM...
local Facing, Momentum= R2s(a+0x78,"EWRAM"),R2s(a+0x7A,"EWRAM")
local z= WordToAngle(Facing)
local x= CompassX + CompassR*math.cos(z)
local y= CompassY + CompassR*math.sin(z)
gui.drawLine(CompassX, CompassY,x,y,0xFFFF00FF)
z= WordToAngle(Momentum)
x= CompassX + CompassR*math.cos(z)
y= CompassY + CompassR*math.sin(z)
gui.drawLine(CompassX, CompassY,x,y,0xFF00FF00)
end
local Extent= RadarR*RadarZ
--*****************************************************************************
local function CloseEnough(x1,y1 , x2,y2)
--*****************************************************************************
--True or false: is the thing within radar range?
return ((x1-Extent) <= x2) and ((x1+Extent) >= x2) and
((y1-Extent) <= y2) and ((y1+Extent) >= y2)
end
local RadarColors= {
[0]=0xFFFFFFFF,0xFF00FF00,0xFFFFFF00,0xFF00FFFF,0xFFFF40FF
}
--*****************************************************************************
local function RivalRadar_North(n) --Input: Who is player?
--*****************************************************************************
--Shows nearby machines.
--It is oriented northward, by the way.
local a= 0x12D60 + n*0xCC --02012D60, a region in EWRAM...
local OriginX,OriginY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
for i= 0, 4 do --We will paint the player as a side-effect here.
a= 0x12D60 + i*0xCC
local MachineX,MachineY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
if (R1s(a+0xB6,"EWRAM") ~= -1) and
CloseEnough(OriginX,OriginY , MachineX,MachineY) then
local X= math.floor((MachineX-OriginX)/RadarZ+0.5) + RadarX
local Y= math.floor((MachineY-OriginY)/RadarZ+0.5) + RadarY
local clr= RadarColors[i] or 0xFFC0C0C0 --Fallback shouldn't happen, but just in case...
gui.drawLine(X-4,Y ,X+4,Y ,clr)
gui.drawLine(X ,Y-4,X ,Y+4,clr)
end
end
end
--*****************************************************************************
local function RivalRadar_Facing(n) --Input: Who is player?
--*****************************************************************************
--Shows nearby machines.
--It is oriented northward, by the way.
local a= 0x12D60 + n*0xCC --02012D60, a region in EWRAM...
local OriginX,OriginY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
local Facing= R2s(a+0x78,"EWRAM")
Facing= WordToAngle(Facing)
local Sine= math.sin(Facing)
local Cosine= math.cos(Facing)
for i= 0, 4 do --We will paint the player as a side-effect here.
a= 0x12D60 + i*0xCC
local MachineX,MachineY= R4s(a+0,"EWRAM"),R4s(a+4,"EWRAM")
if (R1s(a+0xB6,"EWRAM") ~= -1) and
CloseEnough(OriginX,OriginY , MachineX,MachineY) then
local X,Y= MachineX-OriginX,MachineY-OriginY
X,Y= -Sine*X+Cosine*Y, -Cosine*X-Sine*Y
X= math.floor(X/RadarZ+0.5) + RadarX
Y= math.floor(Y/RadarZ+0.5) + RadarY
local clr= RadarColors[i] or 0xFFC0C0C0 --Fallback shouldn't happen, but just in case...
gui.drawLine(X-4,Y ,X+4,Y ,clr)
gui.drawLine(X ,Y-4,X ,Y+4,clr)
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"))) --Speed
-- gui.pixelText( 0, 21,string.format("%8X",R4s(a+0x78,"EWRAM"))) --Facing & Momentum
x= x - R4s(a+0x08,"EWRAM")
y= y - R4s(a+0x0C,"EWRAM")
local v= math.floor(math.sqrt(x*x + y*y)) -- Distance formula
gui.pixelText( 0, 23,string.format("%8X",v),0xFF00FFFF) -- Change in position
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"))) --Pow
gui.pixelText(224, 7,string.format("%4d",R2u(a+0xA2,"EWRAM"))) --Lap seg
gui.pixelText(224,153,string.format("%4d",R2u(a+0x8C,"EWRAM"))) --Boost timer
gui.pixelText(224,145,string.format("%4d",R1u(a+0xA1,"EWRAM"))) --Trigger timer
end
--*****************************************************************************
local function BasicHUD()
--*****************************************************************************
--Generally for basic calculations and all that.
--Also a scratch field for various tests.
--[[
for x= 0, 4 do
for y= 0, 22 do
local addr= 0x12D60 + 0xCC*x + 4*y + 0x80
gui.pixelText(36*x,7*y,string.format("%08X",R4u(addr,"EWRAM")))
end
end
]]--
-- for i= 0, 4 do
-- local addr= 0x12D60 + 0xCC*x + 4*y + 0x80
-- end
end
--Immediate
--*****************************************************************************
while true do
--*****************************************************************************
--Our overhead.
local Player= R1u(0x2B63,"IWRAM")
if Player < 5 then
CompassHUD(Player)
RivalRadar_Facing(Player)
MachineHUD(Player)
end
BasicHUD()
emu.frameadvance()
end
--[[
IWRAM:2B62,1u - Player machine ID
IWRAM:2B63,1u - Player machine memory internal position
EWRAM:0A100,1u[Count=0x4000?] Input log history (4.5 minutes)
EWRAM:12D60[Size=0xCC][Count=5] Machine data
+00,4s - X position (main)
+04,4s - Y position (main)
+08,4s - X position (1 frame ago)
+0C,4s - Y position (1 frame ago)
+10,4s - X position (1 frame ago)
+14,4s - Y position (1 frame ago)
+18,4s - X position (2 frames ago)
+1C,4s - Y position (2 frames ago)
+20,4s - X position (3 frames ago)
+24,4s - Y position (3 frames ago)
+28,4s - X position (4 frames ago)
+2C,4s - Y position (4 frames ago)
+54,4s - Elevation
+74,2s - Speed
+78,2x - Facing
+7A,2x - Momentum
+84,2s - Vertical velocity
+8A,2u - Power
+8C,2u - Boost timer
+8E,2u - Boost timer (mirror)
+94,4x - Apparent health (for that visual health meter?)
+9F,1u - ? Internal reference ID?
+A1,1u - Timer for holding down boost
+A2,1u - Lap position?
+B6,1s - ID?
EWRAM:131CF,1u - ? Player machine selection related?
]]--