SHARE
TWEET

ctinfoscope20160610_coords

redslash Dec 1st, 2016 116 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
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