User File #39461909507580773

Upload All User Files

#39461909507580773 - GBA F-Zero: Maximum Velocity - LuaHawk display tryout

FZMV_BizHawk_v1.lua
828 downloads
Uploaded 6/4/2017 3:51 AM by FatRatKnight (see all 245)
Facing and momentum compass on the lower left.
Rival radar on the lower right.
Various RAM Watch alternatives and minor calculations in various places on the screen.
This is a start. Not sure how helpful the visuals are, but the visuals should hopefully give a decent idea. I use hexadecimal in a lot of places, considering how many important things are apparently nicely divisible by 256, but if those aren't liked, look through the various string.format scattered about and change that X to a d. Or ask me to do that for you and re-upload, I suppose.
I have a soft spot for hexadecimal. Easier for me to remember 0000, 4000, 8000, and C000 for the compass points rather than 0, 16384, 32768, and 49152. So clean.
Anyway, hopefully this script is a nice enough starting point. Some things from an older VBA script was used.
Before I forget, the rival radar has a minor glitch. Namely, I restrict the viewing area to a square, and then rotate it. Whoops, the rotation spins my square around. I really should rotate, then trim to within the square...
--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?
]]--