User File #49139941776852396

Upload All User Files

#49139941776852396 - Earthbound Lua Script for BizHawk

Earthbound Utils.lua
932 downloads
Uploaded 8/14/2018 12:19 AM by brunovalads (see all 13)
An edited version for BizHawk of pirohiko's Snes9x script
-- #########################################
-- #                                       #
-- #  EarthBound Utils Script for BizHawk  #
-- #                                       #
-- #  Author: BrunoValads                  #
-- #                                       #
-- #  Original by pirohiko for Snes9x      #
-- #  https://pastebin.com/z1ueHSZG        #
-- #                                       #
-- #########################################

-- CONFIGURATION --

local Left_gap = 80 -- change these values if the emu doesn't fit in your screen
local Top_gap = 80
local Right_gap = 80
local Bottom_gap = 80

-- MAIN --

local RNG24 = {}
local RNG26 = {}
local RNG   = {}
local bit = 0
local RNGoffset = -70
local RNGend = 14592
local RNGpos = -70
RNG24[RNGoffset] = 4660
RNG26[RNGoffset] = 120
RNG[RNGoffset] = 134
 
for i=RNGoffset+1,RNGend do
  RNG24[i] = math.floor((RNG24[i-1]+bit)/2)+32768*math.fmod(RNG24[i-1]+bit,2)
  RNG26[i] = math.fmod(RNG26[i-1]+109, 256)
  RNG[i] = math.fmod(math.floor(math.fmod(RNG24[i],256)*RNG26[i]/16),256)
  bit = math.fmod(math.floor(math.fmod(RNG24[i],256)*RNG26[i]/4),4)
end
 
function search_RNGpos()
  local cur24 = mainmemory.read_u16_le(0x0024)
  local cur26 = mainmemory.read_u8(0x0026)
  RNGpos = RNGoffset
  for i=RNGoffset, 256 do
    if(RNG26[i]==cur26) then
      for j=i, RNGend, 256 do
        if(RNG24[j]==cur24) then
          RNGpos = j
          break
        end
      end
      break
    end
  end
end
 
function draw_RNGgraph(x,y,width,height) --draw_RNGgraph(0,288,255,32)
  
  local RNG_str = string.format("%5d/%5d", RNGpos, RNGend)
  gui.text(2*256 - 10*string.len(RNG_str) - 2 + 2*Left_gap, 2*224 + 2*Top_gap, RNG_str)
  gui.text(2 + 2*Left_gap, 2*224 + 2*Top_gap, string.format("RNG: %3d", RNG[RNGpos]))
  
  gui.drawBox(x + Left_gap, y-1 + Top_gap, x+width + Left_gap, y+height+1 + Top_gap, 0x50FFFFFF)
  gui.drawLine(x+36 + Left_gap, y+height+2 + Top_gap, x+36 + Left_gap, y-2 + Top_gap, 0xffFFFFFF)
  
  local color
  
  for i=0,width do
    color = 0x8000FF20
    local curRNG = RNG[(RNGpos+i)%14592]
    if curRNG==0 then
      color = 0xffFF1010 -- 1/128 Item Drop
      curRNG=256
    elseif curRNG==128 then
      color = 0xffFFFF30 -- 1/128 Item Drop
    elseif curRNG==255 then
      color = 0xffFF8000 -- MAX
      curRNG=256
    elseif curRNG<=12 then
      color = 0xffFF5050 -- SMAAAASH!!
    elseif curRNG>184 then
      color = 0x900080FF -- No enemies
    end
    gui.drawLine(x+i + Left_gap, y+height + Top_gap, x+i + Left_gap, y+height-math.floor(curRNG/256*height) + Top_gap,color)
  end
  
  x, y = 2*128 + 2*Left_gap - 10*10/2, 2*(y+height) + 2*Top_gap + 4
  color = 0x8000FF20
  gui.text(x, y, "  No use  ", color)
  
  y = y + 14
  color = 0xffFF5050
  gui.text(x, y, "SMAAAASH!!", color)
  
  y = y + 14
  color = 0xff0080FF
  gui.text(x, y, "No enemies", color)
  
  y = y + 14
  color = 0xffFFFF30
  gui.text(x, y, "1/128 Item", color)
end
 
 
function watch_pos()
  
  -- General info
  
  gui.text(2, 2, emu.framecount())
  
  local game_mode = mainmemory.read_u8(0x0015) -- maybe?

  local x, y = 2*128 - 10*15/2 + 2*Left_gap, 2*Top_gap - 28
  local camera_x = mainmemory.read_s16_le(0x0031)
  local camera_y = mainmemory.read_s16_le(0x0033)
  gui.text(x,y, string.format("Camera X: %5d \nCamera Y: %5d", camera_x, camera_y))
  
  if game_mode == 32 then -- map mode
    gui.text(2*(256 + 64 + Left_gap) - 5*10, 2*(-64 + Top_gap), "spawn \n area", 0x80FFFFFF)
    gui.drawBox(-64 + Left_gap, -64 + Top_gap, 256 + 64 + Left_gap, 224 + 64 + Top_gap, 0x80FFFFFF)
  end
  
  --grid
  for i = 0, 15 do
    for j = 0, 13 do
      local x_base = 16*math.floor(camera_x/16)
      local y_base = 16*math.floor(camera_y/16)
      
      local x_origin, y_origin = -camera_x, -camera_y
      --gui.drawRectangle(x_base - camera_x + i*16 + Left_gap, y_base - camera_y + j*16 + Top_gap, 15, 15, 0xA0FFFFFF)
    end
  end
  
  -- Player info
  
  x, y = 2, 2*Top_gap
  local ness_hp = mainmemory.read_u16_le(0x9FBF)
  gui.text(x, y,"Ness HP:  "..ness_hp, 0xffFFFF30)
  
  y = y + 14
  local m = mainmemory.read_s16_le(0x9831)
  gui.text(x, y, "Money:    "..m)
  
  y = y + 14
  local atm = mainmemory.read_s16_le(0x9835)
  gui.text(x, y, "ATM:      "..atm)
  
  y = y + 14
  local ss = mainmemory.read_s16_le(0x9E3C)
  gui.text(x, y, "Skip S.:  "..ss)
  
  y = y + 14
  local dr = mainmemory.read_s16_le(0xA934)
  gui.text(x, y, "Drop   :  "..dr)
  
  y = y + 28
  local xadr = 0x9875
  gui.text(x,y,
    string.format("X-Pos: %5d \n",mainmemory.read_u16_le(xadr+2))..
    string.format("X-Sub: %5d \n",mainmemory.read_u16_le(xadr-0))..
    string.format("Y-Pos: %5d \n",mainmemory.read_u16_le(xadr+6))..
    string.format("Y-Sub: %5d \n",mainmemory.read_u16_le(xadr+4))
  )
  local x_screen = mainmemory.read_u16_le(xadr+2) - camera_x + Left_gap
  local y_screen = mainmemory.read_u16_le(xadr+6) - camera_y + Top_gap
  gui.drawAxis(x_screen, y_screen, 3, 0xffFF0000)
  
  
  -- Battle info
  
  if game_mode == 16 or game_mode == 6 then -- battle mode
    local enemy_hp_str = string.format("HP: %d", mainmemory.read_u16_le(0xA22F))
    gui.text(2*128 - 10*string.len(enemy_hp_str)/2 + 2*Left_gap, 163 + 2*Top_gap, enemy_hp_str, 0xffFFFF30)
  end
  
  
  -- Sprite info
  
  if game_mode == 32 then -- map mode
    for i = 0, 14-1 do -- there are 14 sprite slots, apparently
      local sprite_id = mainmemory.read_u16_le(0x0A62 + 2*i)
      
      if sprite_id ~= 65535 then -- sprite is active
        local sprite_x_pos = mainmemory.read_u16_le(0x0B8E + 2*i)
        local sprite_y_pos = mainmemory.read_u16_le(0x0BCA + 2*i)
        
        local x_screen = sprite_x_pos - camera_x + Left_gap
        local y_screen = sprite_y_pos - camera_y + Top_gap
        
        gui.drawAxis(x_screen, y_screen, 3, 0xffFF0000)
        --gui.drawRectangle(x_screen - 8, y_screen - 24, 16, 32)
        
        local sprite_slot_str = string.format("#%02d", i)
        gui.text(2*x_screen - 10*string.len(sprite_slot_str)/2, 2*y_screen + 14, sprite_slot_str, 0xffFF0000)
        local sprite_id_str = string.format("(%d)", sprite_id)
        gui.text(2*x_screen - 10*string.len(sprite_id_str)/2, 2*y_screen + 28, sprite_id_str, 0xffFF0000)
      end
    end
  end
  
  --[[
  enemy 1 x pos: 0x0B8E
  Ness x pos: 0x0BBE
  2nd partner x pos: 0x0BC6
  1st partner x pos: 0x0BC8
  
  enemy 1 y pos: 0x0BCA
  Ness y pos: 0x0BFA
  2nd partner y pos: 0x0C02
  1st partner y pos: 0x0C04
  
  tables are offset by 0x3C bytes (60 bytes, 30 slots)
  ]]
end
 
event.onframestart(search_RNGpos)

client.SetGameExtraPadding(Left_gap, Top_gap, Right_gap, Bottom_gap)

while true do
  draw_RNGgraph(0,238,255,32)
  watch_pos()
  
  emu.frameadvance()
end