SHARE
TWEET

EarthBound Lua Script

brunovalads Aug 13th, 2018 261 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- #########################################
  2. -- #                                       #
  3. -- #  EarthBound Utils Script for BizHawk  #
  4. -- #                                       #
  5. -- #  Author: BrunoValads                  #
  6. -- #                                       #
  7. -- #  Original by pirohiko for Snes9x      #
  8. -- #  https://pastebin.com/z1ueHSZG        #
  9. -- #                                       #
  10. -- #########################################
  11.  
  12. -- CONFIGURATION --
  13.  
  14. local Left_gap = 80 -- change these values if the emu doesn't fit in your screen
  15. local Top_gap = 80
  16. local Right_gap = 80
  17. local Bottom_gap = 80
  18.  
  19. -- MAIN --
  20.  
  21. local RNG24 = {}
  22. local RNG26 = {}
  23. local RNG   = {}
  24. local bit = 0
  25. local RNGoffset = -70
  26. local RNGend = 14592
  27. local RNGpos = -70
  28. RNG24[RNGoffset] = 4660
  29. RNG26[RNGoffset] = 120
  30. RNG[RNGoffset] = 134
  31.  
  32. for i=RNGoffset+1,RNGend do
  33.   RNG24[i] = math.floor((RNG24[i-1]+bit)/2)+32768*math.fmod(RNG24[i-1]+bit,2)
  34.   RNG26[i] = math.fmod(RNG26[i-1]+109, 256)
  35.   RNG[i] = math.fmod(math.floor(math.fmod(RNG24[i],256)*RNG26[i]/16),256)
  36.   bit = math.fmod(math.floor(math.fmod(RNG24[i],256)*RNG26[i]/4),4)
  37. end
  38.  
  39. function search_RNGpos()
  40.   local cur24 = mainmemory.read_u16_le(0x0024)
  41.   local cur26 = mainmemory.read_u8(0x0026)
  42.   RNGpos = RNGoffset
  43.   for i=RNGoffset, 256 do
  44.     if(RNG26[i]==cur26) then
  45.       for j=i, RNGend, 256 do
  46.         if(RNG24[j]==cur24) then
  47.           RNGpos = j
  48.           break
  49.         end
  50.       end
  51.       break
  52.     end
  53.   end
  54. end
  55.  
  56. function draw_RNGgraph(x,y,width,height) --draw_RNGgraph(0,288,255,32)
  57.  
  58.   local RNG_str = string.format("%5d/%5d", RNGpos, RNGend)
  59.   gui.text(2*256 - 10*string.len(RNG_str) - 2 + 2*Left_gap, 2*224 + 2*Top_gap, RNG_str)
  60.   gui.text(2 + 2*Left_gap, 2*224 + 2*Top_gap, string.format("RNG: %3d", RNG[RNGpos]))
  61.  
  62.   gui.drawBox(x + Left_gap, y-1 + Top_gap, x+width + Left_gap, y+height+1 + Top_gap, 0x50FFFFFF)
  63.   gui.drawLine(x+36 + Left_gap, y+height+2 + Top_gap, x+36 + Left_gap, y-2 + Top_gap, 0xffFFFFFF)
  64.  
  65.   local color
  66.  
  67.   for i=0,width do
  68.     color = 0x8000FF20
  69.     local curRNG = RNG[(RNGpos+i)%14592]
  70.     if curRNG==0 then
  71.       color = 0xffFF1010 -- 1/128 Item Drop
  72.       curRNG=256
  73.     elseif curRNG==128 then
  74.       color = 0xffFFFF30 -- 1/128 Item Drop
  75.     elseif curRNG==255 then
  76.       color = 0xffFF8000 -- MAX
  77.       curRNG=256
  78.     elseif curRNG<=12 then
  79.       color = 0xffFF5050 -- SMAAAASH!!
  80.     elseif curRNG>184 then
  81.       color = 0x900080FF -- No enemies
  82.     end
  83.     gui.drawLine(x+i + Left_gap, y+height + Top_gap, x+i + Left_gap, y+height-math.floor(curRNG/256*height) + Top_gap,color)
  84.   end
  85.  
  86.   x, y = 2*128 + 2*Left_gap - 10*10/2, 2*(y+height) + 2*Top_gap + 4
  87.   color = 0x8000FF20
  88.   gui.text(x, y, "  No use  ", color)
  89.  
  90.   y = y + 14
  91.   color = 0xffFF5050
  92.   gui.text(x, y, "SMAAAASH!!", color)
  93.  
  94.   y = y + 14
  95.   color = 0xff0080FF
  96.   gui.text(x, y, "No enemies", color)
  97.  
  98.   y = y + 14
  99.   color = 0xffFFFF30
  100.   gui.text(x, y, "1/128 Item", color)
  101. end
  102.  
  103.  
  104. function watch_pos()
  105.  
  106.   -- General info
  107.  
  108.   gui.text(2, 2, emu.framecount())
  109.  
  110.   local game_mode = mainmemory.read_u8(0x0015) -- maybe?
  111.  
  112.   local x, y = 2*128 - 10*15/2 + 2*Left_gap, 2*Top_gap - 28
  113.   local camera_x = mainmemory.read_s16_le(0x0031)
  114.   local camera_y = mainmemory.read_s16_le(0x0033)
  115.   gui.text(x,y, string.format("Camera X: %5d \nCamera Y: %5d", camera_x, camera_y))
  116.  
  117.   if game_mode == 32 then -- map mode
  118.     gui.text(2*(256 + 64 + Left_gap) - 5*10, 2*(-64 + Top_gap), "spawn \n area", 0x80FFFFFF)
  119.     gui.drawBox(-64 + Left_gap, -64 + Top_gap, 256 + 64 + Left_gap, 224 + 64 + Top_gap, 0x80FFFFFF)
  120.   end
  121.  
  122.   -- Player info
  123.  
  124.   x, y = 2, 2*Top_gap
  125.   local ness_hp = mainmemory.read_u16_le(0x9FBF)
  126.   gui.text(x, y,"Ness HP:  "..ness_hp, 0xffFFFF30)
  127.  
  128.   y = y + 14
  129.   local m = mainmemory.read_s16_le(0x9831)
  130.   gui.text(x, y, "Money:    "..m)
  131.  
  132.   y = y + 14
  133.   local atm = mainmemory.read_s16_le(0x9835)
  134.   gui.text(x, y, "ATM:      "..atm)
  135.  
  136.   y = y + 14
  137.   local ss = mainmemory.read_s16_le(0x9E3C)
  138.   gui.text(x, y, "Skip S.:  "..ss)
  139.  
  140.   y = y + 14
  141.   local dr = mainmemory.read_s16_le(0xA934)
  142.   gui.text(x, y, "Drop   :  "..dr)
  143.  
  144.   y = y + 28
  145.   local xadr = 0x9875
  146.   gui.text(x,y,
  147.     string.format("X-Pos: %5d \n",mainmemory.read_u16_le(xadr+2))..
  148.     string.format("X-Sub: %5d \n",mainmemory.read_u16_le(xadr-0))..
  149.     string.format("Y-Pos: %5d \n",mainmemory.read_u16_le(xadr+6))..
  150.     string.format("Y-Sub: %5d \n",mainmemory.read_u16_le(xadr+4))
  151.   )
  152.   local x_screen = mainmemory.read_u16_le(xadr+2) - camera_x + Left_gap
  153.   local y_screen = mainmemory.read_u16_le(xadr+6) - camera_y + Top_gap
  154.   gui.drawAxis(x_screen, y_screen, 3, 0xffFF0000)
  155.  
  156.  
  157.   -- Battle info
  158.  
  159.   if game_mode == 16 or game_mode == 6 then -- battle mode
  160.     local enemy_hp_str = string.format("HP: %d", mainmemory.read_u16_le(0xA22F))
  161.     gui.text(2*128 - 10*string.len(enemy_hp_str)/2 + 2*Left_gap, 163 + 2*Top_gap, enemy_hp_str, 0xffFFFF30)
  162.   end
  163.  
  164.  
  165.   -- Sprite info
  166.  
  167.   if game_mode == 32 then -- map mode
  168.     for i = 0, 14-1 do -- there are 14 sprite slots, apparently
  169.       local sprite_id = mainmemory.read_u16_le(0x0A62 + 2*i)
  170.      
  171.       if sprite_id ~= 65535 then -- sprite is active
  172.         local sprite_x_pos = mainmemory.read_u16_le(0x0B8E + 2*i)
  173.         local sprite_y_pos = mainmemory.read_u16_le(0x0BCA + 2*i)
  174.        
  175.         local x_screen = sprite_x_pos - camera_x + Left_gap
  176.         local y_screen = sprite_y_pos - camera_y + Top_gap
  177.        
  178.         gui.drawAxis(x_screen, y_screen, 3, 0xffFF0000)
  179.         --gui.drawRectangle(x_screen - 8, y_screen - 24, 16, 32)
  180.        
  181.         local sprite_slot_str = string.format("#%02d", i)
  182.         gui.text(2*x_screen - 10*string.len(sprite_slot_str)/2, 2*y_screen + 14, sprite_slot_str, 0xffFF0000)
  183.         local sprite_id_str = string.format("(%d)", sprite_id)
  184.         gui.text(2*x_screen - 10*string.len(sprite_id_str)/2, 2*y_screen + 28, sprite_id_str, 0xffFF0000)
  185.       end
  186.     end
  187.   end
  188.  
  189.   --[[
  190.   enemy 1 x pos: 0x0B8E
  191.   Ness x pos: 0x0BBE
  192.   2nd partner x pos: 0x0BC6
  193.   1st partner x pos: 0x0BC8
  194.  
  195.   enemy 1 y pos: 0x0BCA
  196.   Ness y pos: 0x0BFA
  197.   2nd partner y pos: 0x0C02
  198.   1st partner y pos: 0x0C04
  199.  
  200.   tables are offset by 0x3C bytes (60 bytes, 30 slots)
  201.   ]]
  202. end
  203.  
  204. event.onframestart(search_RNGpos)
  205.  
  206. client.SetGameExtraPadding(Left_gap, Top_gap, Right_gap, Bottom_gap)
  207.  
  208. while true do
  209.   draw_RNGgraph(0,238,255,32)
  210.   watch_pos()
  211.  
  212.   emu.frameadvance()
  213. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top