Advertisement
redslash

ctinfoscope20160610_coords

Dec 1st, 2016
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.66 KB | None | 0 0
  1. --Chrono Trigger Infoscope for Snes9x(1.51-rr)
  2. -- 2015-06-10 Redslash
  3. --RNG Display shows how much window remains; Input Display shows press vs. hold (works with movies!); Room Timer can use a savestate (most recent only); Upcoming Crits (next 6); Hitbox Viewer (experimental, kinda laggy); and Coordinates highlight odd/even pixel.
  4.  
  5. --<Select> hides some displays.
  6.  
  7. local inputs = joypad.get()
  8. local button =  {'R','L','X','A','right','left','down','up','start','select','Y','B'}
  9. local xcoords = { 8.6, 0.5, 9,10, 2, 0, 1, 1, 6, 4, 8, 9}
  10. local ycoords = {  1,   1,  2, 3, 3, 3, 4, 2, 3, 3, 3, 4}
  11. local pressdur = { 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  12. local selectheld = 0
  13.  
  14.  
  15. local dispbox = 3 -- (press select to toggle)
  16. local yoffset = 191
  17. local xoffset = 97 -- 89 = button display centered
  18. local regcolor = "#CCCCCC"
  19.  
  20. local BATTLE_FLAG = 0x7e0117
  21. local battleflag = 0
  22. local battlecopy = 0
  23.  
  24. local LOCATION = 0x7e0100
  25. local loc = 0
  26.  
  27. local frame,batstart,locstart = 0,0,0
  28. local timesav,batsav,locsav = 0,0,0
  29. local timeend = 0
  30. local recentload = 0
  31.  
  32. function displayTime()
  33.  
  34.     frame = frame + 1
  35.  
  36. --Catch battleflag change
  37.     if battleflag ~= memory.readbyte(BATTLE_FLAG) % 2 then
  38.         battleflag = memory.readbyte(BATTLE_FLAG) % 2
  39.         if battleflag == 0 then
  40.             timeend = frame - batstart
  41.         else timeend = frame - locstart end
  42.         if battleflag == 1 and recentload == 0 then batstart = frame end       
  43.     end
  44. --Catch location change
  45.     if loc ~= memory.readword(LOCATION) then
  46.         loc = memory.readword(LOCATION)
  47.         timeend = frame - locstart
  48.         if recentload == 0 then locstart = frame end
  49.     end
  50.     recentload = 0
  51.  
  52.     gui.text(xoffset+14,yoffset+26,"  "..string.format("%2d'%02d\"%02d",
  53.         (timeend + 1) % 216000 / 3600, ((timeend + 1) % 3600) / 60, (timeend + 1) % 60), regcolor)
  54. end
  55.  
  56.  
  57. local BATTLE_VALUE = 0x7e0026
  58. local BATTLE_STORE = 0x7e29AD
  59. local CRIT_VALUE = 0x7eB3E6
  60. local MENU_TIME = 0x7e0D00
  61. local menutime = 0
  62. local menuopen = 0
  63.  
  64. local CHAR_ID = 0x7e2980  -- 3 in-party then 6 reserve (e.g. for 1-on-1 bosses)
  65. local CHAR_WEAP = 0x7e2629
  66. local CHAR_ACC = 0x7e262A
  67.  
  68. local chars = {}
  69. local charname = {"C","M","L","R","F","A","J"}
  70.  
  71. local windowname =  {"1-","1+","2-","2+","3-","3+","4-","4+","5-","5+","6-","6+","7-","7+","8-","8+"}
  72. local battlewindow = {0x00,0x09,0x0d,0x1d,0x2e,0x37,0x3e,0x58,0x61,0x88,0x98,0xab,0xb9,0xdc,0xe3,0xfb,0x100,
  73.                      0x00,0x0d,0x12,0x17,0x35,0x40,0x5c,0x67,0x6a,0x88,0x8f,0xad,0xb3,0xd0,0xe4,0xfd,0x100,
  74.                      0x00,0x0b,0x18,0x1d,0x2c,0x33,0x64,0x66,0x6d,0x79,0x85,0xa7,0xb6,0xd3,0xe6,0xf7,0x100,0x00}
  75.                      --set of windows for 0, 1, and 2 empty characters
  76.  
  77. local crits =   "0737062067712743017053012106621026206760245002737143667207070014"..
  78.                 "1101674231747620560305126422403270125313166113731602620666773021"..
  79.                 "1714114244363074011420427072702021156152710015037100071773030063"..
  80.                 "3110560024303132144471071671003163600200333701061633241110004006"..
  81.                 "0737062067" --wrap-around
  82.  
  83. function displayValues()
  84.    
  85. --Catch the BV copy
  86.     if battlecopy == 0 and battleflag == 1 and memory.readbyte(BATTLE_VALUE) == memory.readbyte(BATTLE_STORE) then
  87.             battlecopy = 1
  88.     elseif battleflag == 0 then
  89.         battlecopy = 0
  90.     end
  91.  
  92. --Value is at different address for in-battle, out-of-battle, & load menu:
  93.     if battlecopy == 1 then
  94.         bv = memory.readbyte(BATTLE_VALUE)
  95.         cv = memory.readbyte(CRIT_VALUE)
  96.     else
  97.         if (memory.readbyte(MENU_TIME) > 0 and memory.readbyte(BATTLE_STORE) == 0 and emptychars == 0) then
  98.         --menutime is for ALL menus, BV is 0 for entire beginning... but load menu has "3 Crono's" (000000)
  99.             bv = memory.readbyte(MENU_TIME)
  100.         else bv = memory.readbyte(BATTLE_STORE) end
  101.         cv = bv
  102.     end
  103.    
  104. --Get the active PCs
  105.     emptychars = 0
  106.     for i = 1,3 do
  107.         chars[i] = memory.readbyte(CHAR_ID+i-1)
  108.         if chars[i] >= 0x07 then emptychars = emptychars + 1 end
  109.     end
  110.  
  111. --Draw values:
  112.     if emptychars < 3 then
  113.         for i = 1, 16 do
  114.             if bv >= battlewindow[emptychars*17 + i] and bv < battlewindow[emptychars*17 + i + 1] then
  115.                 gui.text(4, yoffset+18, "RNG: " .. string.format("%2X",bv)..
  116.                     " (left " .. string.format("%2d", battlewindow[emptychars*17+ i + 1] - bv) .. ")",regcolor)
  117.                 gui.text(4, yoffset+26, "Load Window: " .. windowname[i],regcolor)
  118.             end
  119.         end
  120.     end
  121. end
  122.  
  123.  
  124. function displayCrits()
  125.  
  126. --Get equipment and their crit chance
  127.     chance = 0
  128.     crittext = ""
  129.     for i = 1,3 do
  130.         if chars[i] < 0x07 then
  131.             weap = memory.readbyte(CHAR_WEAP + 0x50*(chars[i]))
  132.             acc = memory.readbyte(CHAR_ACC + 0x50*(chars[i]))
  133.             if     weap == 0x55 then chance = 1                                     -- rainbow
  134.             elseif acc  == 0xB3 and (weap == 0x42 or weap == 0x3D) then chance = 2  -- masamune + heromedal
  135.             elseif weap == 0x40 or   weap == 0x19 or weap == 0x1A  then chance = 3  -- wonder, siren, valkerye
  136.             elseif weap == 0x53 then chance = 4                                     -- swallow
  137.             elseif weap == 0x54 or charname[chars[i]+1] == "F" or charname[chars[i]+1] == "A" then chance = 5   -- slasher2 (22)
  138.             elseif weap == 0x0D or charname[chars[i]+1] == "M" or charname[chars[i]+1] == "L" then chance = 6   -- kaliblade
  139.             elseif charname[chars[i]+1] == "C" or charname[chars[i]+1] == "R" or charname[chars[i]+1] == "J" then chance = 7 end
  140.             space = " "
  141.             if chance ~= 7 then space = "+ " end
  142.             crittext = crittext .. charname[chars[i]+1] .. "=" .. chance .. space
  143.         end
  144.     end
  145.  
  146.     gui.text(202,yoffset+18,"Crits: "..string.sub(crits, cv+1, cv+6), regcolor)
  147.     if emptychars == 2 then
  148.         gui.text(202, yoffset+26, " Crono=7 ",regcolor)
  149.     else gui.text(202, yoffset+26, crittext, regcolor) end
  150. end
  151.  
  152.  
  153. local FACING = 0x7e1600
  154. local MOVING = 0x7e1680
  155. local facing = {}
  156. local moving = {}
  157. local faceoffset = 5    -- experimental
  158. local MAP_X = 0x7e1800
  159. local MAP_Y = 0x7e1880
  160. local mapx = {}
  161. local mapy = {}
  162. local mapoffsetx = 0
  163. local mapoffsety = 0
  164. local SCREEN_X = 0x7e0A00
  165. local SCREEN_Y = 0x7e0A80
  166. local mainsprite = 0
  167. local farsprite = 0
  168. local xsign,ysign = "",""
  169. local xcolor,ycolor = 0,0
  170.  
  171. function displayHitbox()
  172.  
  173.     for i = 1,64 do
  174.         mapx[i] = math.floor(memory.readword(MAP_X + 2*(i-1))/16)
  175.         mapy[i] = math.floor(memory.readword(MAP_Y + 2*(i-1))/16)
  176.         facing[i] = memory.readbyte(FACING + 2*(i-1))
  177.         if memory.readbyte(MOVING + 2*(i-1)) > 0 then
  178.             moving[i] = 1
  179.         else moving[i] = 0 end
  180.     end
  181.        
  182.     mainsprite = 0
  183.     farsprite = 0
  184.     for i = 1,16 do     -- get one sprite to compare
  185.         spritex = memory.readword(SCREEN_X + 2*(i-1))
  186.         spritey = memory.readword(SCREEN_Y + 2*(i-1))
  187.         if spritex > 0 and spritey > 0 and mapx[i] ~= 0xFF0 and mapx[i] ~= 0xFF8 and mapx[i] ~= 0x178 and mapx[i] ~= 0x088 then
  188.             if mainsprite == 0 then
  189.                 mapoffsetx = mapx[i] - spritex
  190.                 mapoffsety = mapy[i] - spritey
  191.                 mainsprite = i
  192.             elseif farsprite == 0 then
  193.                 farsprite = i
  194.             elseif farsprite > 0 and i < 9 then
  195.                 if (mapx[i]-mapx[mainsprite])^2 + (mapy[i]-mapy[mainsprite])^2 >
  196.                 (mapx[farsprite]-mapx[mainsprite])^2 + (mapy[farsprite]-mapy[mainsprite])^2 then
  197.                     farsprite = i
  198.                     break
  199.                 end
  200.             end
  201.         end
  202.     end
  203.        
  204.     if mapx[mainsprite] ~= nil then
  205.         if mapx[mainsprite]%2 == 1 then xcolor = "#CC4040" else xcolor = regcolor end
  206.         if mapy[mainsprite]%2 == 1 then ycolor = "#CC4040" else ycolor = regcolor end
  207.         gui.text(210,yoffset+18, "P1: ",regcolor)
  208.         gui.text(226,yoffset+18,string.format("%03X",mapx[mainsprite]),xcolor)
  209.         gui.text(242,yoffset+18,string.format("%03X",mapy[mainsprite]),ycolor)
  210.     end
  211.     if mapx[farsprite] ~= nil then
  212.         xdiff = mapx[farsprite] - mapx[mainsprite]
  213.         ydiff = mapy[farsprite] - mapy[mainsprite]
  214.         if xdiff > 0 then xsign = "+" else xsign = "-" end
  215.         if ydiff > 0 then ysign = "+" else ysign = "-" end     
  216.         gui.text(206,yoffset+26, " P3: "..xsign..string.format("%2X",math.abs(xdiff)).." "..
  217.                                         ysign..string.format("%2X",math.abs(ydiff)),regcolor)
  218.     end
  219.  
  220.     for i = 1,64 do
  221.         screenx = mapx[i] - mapoffsetx - 8
  222.         screeny = mapy[i] - mapoffsety - 16
  223.         if screenx < 240 and screeny < 208 then
  224. --[[
  225.             if i < 9 then color = "#0000ff00" else color = "#00ff0000" end
  226.             if     facing[i] == 0 then
  227.                 gui.box(screenx+0, screeny-faceoffset*moving[i], screenx+15, screeny+15-faceoffset, color) --up
  228.             elseif facing[i] == 1 then
  229.                 gui.box(screenx+0, screeny+faceoffset, screenx+15, screeny+15+faceoffset*moving[i], color) --down
  230.             elseif facing[i] == 2 then
  231.                 gui.box(screenx-faceoffset*moving[i], screeny+0, screenx+15-faceoffset, screeny+15, color) --left
  232.             elseif facing[i] == 3 then
  233.                 gui.box(screenx+faceoffset, screeny+0, screenx+15+faceoffset*moving[i], screeny+15, color) --right
  234.             else
  235.                 gui.box(screenx+0, screeny+0, screenx+15, screeny+15, color) end
  236. ]]
  237.                 gui.text(screenx+faceoffset, screeny+faceoffset, string.format("%x",2*(i-1)),"#80808080","#00000000")
  238.         end
  239.     end
  240.  
  241. end
  242.  
  243.  
  244. local emuframe = 0
  245. local moviedata = {}
  246. local movieoffset = 0
  247.  
  248. function displayJoypad()
  249.  
  250.     emuframe = emu.framecount()
  251.  
  252. --Read in movie file:
  253.     if movie.mode() == "playback" and movieoffset == 0 then
  254.         f = io.open(movie.name(), "rb")
  255.         byte = f:read(1)
  256.         while byte ~= nil do
  257.             byte = string.byte(byte)
  258.             table.insert(moviedata, byte)
  259.             byte = f:read(1)
  260.         end
  261.         f:close()
  262.         for i = 0,3 do
  263.             movieoffset = movieoffset + moviedata[0x1C+1+i]*(0x100^i)
  264.         end
  265.     end
  266.    
  267. --Get inputs either from movie or user:
  268.     if movie.mode() == "playback" then
  269.         word = moviedata[movieoffset + emuframe*2 + 1] + moviedata[movieoffset + emuframe*2]*0x100
  270.         word = math.floor(word / 16)  --discard 4 lowest bits; Lua uses all doubles (floating point)
  271.         for i = 1, 12 do
  272.             if word % 2 == 1 then
  273.                 inputs[ button[i] ] = true
  274.             else inputs[ button[i] ] = nil end
  275.             word = math.floor(word / 2)
  276.         end
  277.     else inputs = joypad.get() end
  278.  
  279. --Draw each button (color it based on hold duration):
  280.     for i = 1, 12 do
  281.         if inputs[button[i]] then
  282.             if pressdur[i] > 0 then
  283.                 if pressdur[i] < 250 then
  284.                     pressdur[i] = pressdur[i] + 4
  285.                 end
  286.             else pressdur[i] = 4 end
  287.         else
  288.             if pressdur[i] < 0 then
  289.                 if pressdur[i] > -250 then
  290.                     pressdur[i] = pressdur[i] - 4
  291.                 end
  292.             else pressdur[i] = -4 end
  293.         end
  294.        
  295.         shoulder = 0
  296.         if i == 1 or i == 2 then shoulder = 1 end
  297.        
  298.         if pressdur[i] > 0 then
  299.             gui.box(
  300.             xoffset+xcoords[i]*7, yoffset+ycoords[i]*6,
  301.             xoffset+xcoords[i]*7+7 + shoulder*7, yoffset+ycoords[i]*6+6 - shoulder*3,
  302.             "#ff"..string.format("%02x",pressdur[i]).."00".."ff", "#FFFFFFFF")
  303.         else darken = string.rep(string.format("%02x",0xFF + pressdur[i]/4),3)
  304.             gui.box(
  305.             xoffset+xcoords[i]*7, yoffset+ycoords[i]*6,
  306.             xoffset+xcoords[i]*7+7 + shoulder*7, yoffset+ycoords[i]*6+6 - shoulder*3,
  307.             "#00".."00".."FF"..string.format("%02x",0xFF+pressdur[i]), "#"..darken.."FF") end
  308.     end
  309.     gui.text(xoffset+30,209,"-",regcolor,"#00000000") --attn: select button
  310. end
  311.  
  312.  
  313. function Saving()
  314.     timesav = frame
  315.     locsav = locstart
  316.     batsav = batstart end
  317. savestate.registersave(Saving) -- for room timing, only works with MOST RECENT state
  318. function Reload()
  319.     frame = timesav
  320.     locstart = locsav
  321.     batstart = batsav
  322.     recentload = 1 end
  323. savestate.registerload(Reload)
  324.  
  325.  
  326. while true do
  327.  
  328.     inputs = joypad.get()
  329.    
  330. --Catch <select> pressed
  331.     if inputs[ button[10] ] then
  332.         if selectheld == 0 then
  333.             selectheld = 1
  334.             if dispbox == 3 then
  335.                 dispbox = 0
  336.             else dispbox = dispbox + 1 end
  337.         end
  338.     else selectheld = 0 end
  339. --Catch menu
  340.     if menutime ~= memory.readbyte(MENU_TIME) then
  341.         if menuopen == 0 then
  342.             menuopen = 1 end
  343.     else menuopen = 0 end
  344.     menutime = memory.readbyte(MENU_TIME)
  345.    
  346. --Display all
  347.     displayValues()
  348.     displayTime()
  349.     if (dispbox == 2 or dispbox == 3) and battleflag == 0 and loc < 0x1F0 and menuopen == 0 then
  350.             displayHitbox()
  351.         else displayCrits() end
  352. --  if dispbox == 1 or dispbox == 3 then displayJoypad()
  353. --      else gui.text(xoffset, 208, "  room/battle time","#808080") end
  354.     emu.frameadvance()
  355. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement