Advertisement
yoshifan

[Old] SMG2 Lua script for Dolphin + Cheat Engine

Sep 20th, 2013
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.90 KB | None | 0 0
  1. -- This script has been superseded by:
  2. -- https://github.com/yoshifan/ram-watch-cheat-engine
  3. -- This script might be simpler to use in some ways, but it's not likely
  4. -- to work on newer Dolphin versions.
  5.  
  6.  
  7.  
  8. -- Script to display stuff on the screen of Dolphin.
  9. --
  10. -- 2013 Aug 26 - Created (Masterjun) (http://pastebin.com/vUCmhwMQ)
  11. -- 2013 Sep 17 - Modified to have permanent addresses for "Textures
  12. -- created" and the frame counter, and to tolerate game start addresses
  13. -- greater than 0x7FFFFFFF (yoshifan) (http://pastebin.com/4MsADD5W)
  14. -- 2013 Sep 29 - Modified to track SMG2 addresses, and optionally output
  15. -- stats to a file (yoshifan)
  16. --
  17. -- You need to change the variables that are listed after the functions.
  18. -- And make sure that you checked "Graphics > Advanced > Show Statistics".
  19.  
  20. --------------------------------------------------------------------------------
  21. --------------------------------------------------------------------------------
  22.  
  23. --appends a string s to a table t as hex values
  24. local function appendstr(t,s)
  25.   for i=1,#s do table.insert(t,string.byte(string.sub(s,i,i))) end
  26.   table.insert(t,0x0A)
  27.   return t
  28. end
  29.  
  30. --converts a number into float
  31. local function tofloat(x)
  32.   if x==0 then return 0 end
  33.   local s = 1
  34.   if x>=0x80000000 then
  35.      s = -1
  36.      x=x-0x80000000
  37.   end
  38.   local e = math.floor(x/0x800000)-127
  39.   local m=(x%0x800000)/0x800000+1
  40.   return s*(2^e)*m
  41. end
  42.  
  43. --converts a table of bytes to a string
  44. local function tabletostr(x)
  45.   local s = ""
  46.   for k,v in pairs(x) do s=s..string.format("%02X",v) end
  47.   return s
  48. end
  49.  
  50. --converts a table of bytes (little endian) to a string
  51. local function tableLittleEndianToStr(x)
  52.   local s = ""
  53.   for k,v in pairs(x) do s=string.format("%02X",v)..s end
  54.   return s
  55. end
  56.  
  57. -- table of bytes (little endian) -> number
  58. local function tableLittleEndianToNumber(x)
  59.   local littleEndianStr = tableLittleEndianToStr(x)
  60.   return tonumber(littleEndianStr, 16)
  61. end
  62.  
  63. -- table -> float
  64. local function tabletofloat(x)
  65.   return tofloat(tonumber(tabletostr(x), 16))
  66. end
  67.  
  68. -- float -> string. The number of decimal places can be optionally specified
  69. local function floattostr(x,precision)
  70.   if not precision then
  71.     precision = 3
  72.   end
  73.   format_str = "%." .. precision .. "f"
  74.   local s = string.format(format_str, x)
  75.   return s
  76. end
  77.  
  78. -- 4byte table representing a float -> string representing that float.
  79. -- The number of decimal places can be optionally specified
  80. local function toflstr(x,precision)
  81.   local str_x = tabletostr(x)
  82.   local hex_x = tonumber(str_x,16)
  83.   return floattostr(tofloat(hex_x),precision)
  84. end
  85.  
  86. --scans for a string and returns the address of the first result
  87. --if there is no result it returns nil
  88. local function scanstr(str)
  89.   local startaddr=0
  90.   local stopaddr=0x7fffffffffffffff
  91.   local scan = createMemScan()
  92.   scan.OnlyOneResult=true
  93.   scan.firstScan(soExactValue,vtString,rtTruncated,str,"",startaddr,stopaddr,
  94.   "+W-C",fsmNotAligned,"",false,false,false,true)
  95.   scan.waitTillDone()
  96.   return scan.getOnlyResult()
  97. end
  98.  
  99. --------------------------------------------------------------------------------
  100. --------------------------------------------------------------------------------
  101. -- And again make sure that you checked "Graphics > Advanced > Show Statistics".
  102.  
  103. ----
  104. -- Enter here if you have 64bit Dolphin
  105. local DolphinIs64bit = true
  106. ----
  107.  
  108. -- You must set the following addresses for your version of Dolphin. Since
  109. -- addresses are written in hex, make sure you have the "0x" before the
  110. -- actual number.
  111.  
  112. -----
  113. -- Follow this: http://tasvideos.org/forum/t/13462 tutorial to get a
  114. -- "pointerscan result". Doubleclick on the Address column and enter the address
  115. -- after the ' "Dolphin.exe"+ ' (don't forget the 0x).
  116. local GameRAMStartPointerAddress = 0x04961818
  117. -----
  118.  
  119. -----
  120. -- Choose "String" for Value Type and start a Scan searching "Textures created".
  121. -- There should be only one result.
  122. --
  123. -- Next, take the result's address and scan for it. Have the Value Type set to
  124. -- "4 Bytes", and make sure the "Hex" box is checked. Find the result with a
  125. -- green address.
  126. --
  127. -- Rightclick this green address and click "Disassemble this memory region".
  128. -- Enter the number after the "Dolphin.exe+" at the top.
  129. local TexturesCreatedPointerAddress = 0x00D7D3A0
  130. -----
  131.  
  132. -----
  133. -- Set the Value Type to "Array of byte" and uncheck "Writable" under Memory
  134. -- Scan Options. Make sure the "Hex" box is checked and search for
  135. --
  136. -- 48 63 D8 48 03 DF 48 83 7D C0 10
  137. -- if you have 64 bit Dolphin
  138. --
  139. -- 83 C4 0C 83 7C 24 1C 10 8D 3C 06
  140. -- if you have 32 bit Dolphin
  141. --
  142. -- There should be one result, rightclick that resuld and click "Disassemble
  143. -- this memory region". Enter the number after the "Dolphin.exe+" at the top.
  144. --
  145. -- Make sure to check "Writable" again, and really check it, because it has
  146. -- three states
  147. local ArrayOfBytesAddress = 0x00425671
  148. -----
  149.  
  150. -----
  151. -- "local FrameCounterAddress = nil" if you don't want it.
  152. -- Not necessary but it adds a neat Frame- and Movecounter to the screen.
  153. -- When playing or recording a movie scan for the VI-Count+1 (on the top of the
  154. -- game window) and setting the Value Type to 4 Bytes. The first result should
  155. -- be a green address. Rightclick that result and click "Disassemble this
  156. -- memory region". Enter the number after the "Dolphin.exe+" at the top.
  157. local FrameCounterAddress = 0x0496B6A0
  158. -----
  159.  
  160. -----
  161. -- When you want to output some stats to a file, set this to the number
  162. -- of frames you want to take stats for, and then click "Execute Script"
  163. -- again.
  164. -- If you don't want to output stats to a file, set this to 0.
  165. local stats_frames_to_take = 0
  166. -----
  167.  
  168.  
  169. local stats_current_frame = 1
  170.  
  171. local stats = {}  -- array
  172. local pos_x_initial = nil
  173. local pos_y_initial = nil
  174. local pos_z_initial = nil
  175.  
  176. --------------------------------------------------------------------------------
  177. --------------------------------------------------------------------------------
  178.  
  179. debug_removeBreakpoint(getAddress("Dolphin.exe")+ArrayOfBytesAddress)
  180. debug_setBreakpoint(getAddress("Dolphin.exe")+ArrayOfBytesAddress)
  181.  
  182. function debugger_onBreakpoint()
  183.  
  184.   local mode=""
  185.   if FrameCounterAddress then
  186.     local fcaddr=getAddress("Dolphin.exe")+FrameCounterAddress
  187.     local curfc=readInteger(fcaddr)
  188.     local fc=readInteger(fcaddr+0x08)
  189.     local readonly=readBytes(fcaddr-((DolphinIs64bit and 0x30) or 0x28))
  190.     mode=curfc.." [recording]"
  191.     if readonly==2 then mode=curfc.."/"..fc.." [playback]"
  192.     elseif readonly==0 then mode=curfc.."/"..fc.." [inactive]" end
  193.   end
  194.  
  195.  
  196.   -- We use readBytes() instead of readInteger() here, because readInteger()
  197.   -- can't handle values greater than the max integer-type value, which
  198.   -- is 0x7FFFFFFF.
  199.   local oBytes = readBytes(getAddress("Dolphin.exe")+GameRAMStartPointerAddress,4,true)
  200.   local o = tableLittleEndianToNumber(oBytes)
  201.  
  202.   -- local variable_name = readBytes(addressoffset+o,4,true)
  203.   local ref_pointer2_address = 0x80C7A2C8
  204.   local ref_pointer2_bytes = readBytes(ref_pointer2_address+o,4,true)
  205.  
  206.   local ref_pointer1_address = tonumber(tabletostr(ref_pointer2_bytes),16) + 0x750
  207.   local ref_pointer1_bytes = readBytes(ref_pointer1_address+o,4,true)
  208.   local ref_pointer = tonumber(tabletostr(ref_pointer1_bytes),16)
  209.  
  210.   local pos_start = o + ref_pointer - 0x8670
  211.   local pos_x = readBytes(pos_start,4,true)
  212.   local pos_y = readBytes(pos_start+0x4,4,true)
  213.   local pos_z = readBytes(pos_start+0x8,4,true)
  214.  
  215.   local vel_start = o + ref_pointer - 0x8C20
  216.   local vel_x = readBytes(vel_start,4,true)
  217.   local vel_y = readBytes(vel_start+0x4,4,true)
  218.   local vel_z = readBytes(vel_start+0x8,4,true)
  219.  
  220.   if pos_x == nil then
  221.     -- We're reading a non-readable address. Must be switching between
  222.     -- Mario and Luigi, or just starting up the game.
  223.     return 1
  224.   end
  225.  
  226.   local vel_x_float = tabletofloat(vel_x)
  227.   local vel_y_float = tabletofloat(vel_y)
  228.   local vel_z_float = tabletofloat(vel_z)
  229.   local speed_xz_float = math.sqrt(
  230.     vel_x_float*vel_x_float + vel_z_float*vel_z_float
  231.   )
  232.   local speed_xyz_float = math.sqrt(
  233.     vel_x_float*vel_x_float + vel_y_float*vel_y_float + vel_z_float*vel_z_float
  234.   )
  235.  
  236.  
  237.   local t = {0x0A,0x0A,0x0A,0x0A}
  238.   --0x0A = new line. This makes the display start a few lines down.
  239.  
  240.   t = appendstr(t, mode)
  241.   t = appendstr(t, "")
  242.   t = appendstr(t, "XZ speed: " .. floattostr(speed_xz_float))
  243.   t = appendstr(t, string.format(
  244.     "XZ position: %s | %s", toflstr(pos_x,1), toflstr(pos_z,1)
  245.   ))
  246.   t = appendstr(t, "Y velocity: " .. toflstr(vel_y))
  247.   t = appendstr(t, "Y position: " .. toflstr(pos_y))
  248.   t = appendstr(t, "XYZ speed: " .. floattostr(speed_xyz_float))
  249.  
  250.   table.insert(t,0x00)
  251.   --0x00 = end of text
  252.  
  253.  
  254.   local textures_created_address = readInteger(
  255.     getAddress("Dolphin.exe")+TexturesCreatedPointerAddress
  256.   )
  257.   writeBytes(textures_created_address,t)
  258.   -- You can run the following lines in Cheat Engine's Lua Engine
  259.   -- (in Memory Viewer, Tools -> Lua Engine) to verify that this address has
  260.   -- the string "Textures Created".
  261.   --print(string.format("Address: 0x%08X",textures_created_address))
  262.   --local textures_created_string = readString(textures_created_address,16)
  263.   --print("String: "..textures_created_string)
  264.  
  265.  
  266.   -- Take some statistics on each frame. If
  267.   -- stats_frames_to_take is 0, then this doesn't do anything.
  268.   if stats_current_frame <= stats_frames_to_take then
  269.  
  270.     -- XZ Speed
  271.     --stats[stats_current_frame] = floattostr(speed_xz_float)
  272.  
  273.     -- XZ Distance
  274.     --local pos_x_float = tabletofloat(pos_x)
  275.     --local pos_z_float = tabletofloat(pos_z)
  276.     --if not pos_x_initial then
  277.     --  pos_x_initial = pos_x_float
  278.     --  pos_z_initial = pos_z_float
  279.     --end
  280.     --distance_xz_float = math.sqrt(
  281.     --  (pos_x_float-pos_x_initial)*(pos_x_float-pos_x_initial) + (pos_z_float-pos_z_initial)*(pos_z_float-pos_z_initial)
  282.     --)
  283.     --stats[stats_current_frame] = floattostr(distance_xz_float,6)
  284.  
  285.     -- Y Velocity
  286.     --stats[stats_current_frame] = toflstr(vel_y)
  287.  
  288.     -- Y Position Change
  289.     local pos_y_float = tabletofloat(pos_y)
  290.     if not pos_y_initial then
  291.       pos_y_initial = pos_y_float
  292.     end
  293.     local y_pos_change_float = pos_y_float - pos_y_initial
  294.     stats[stats_current_frame] = toflstr(y_pos_change_float,6)
  295.    
  296.     if stats_current_frame == stats_frames_to_take then
  297.       -- Done taking stats. Collect them in string form and write them
  298.       -- to a file.
  299.      
  300.       stats_str = table.concat(stats, "\n")
  301.      
  302.       -- This file will be created in either:
  303.       -- (A) The same directory as the cheat table you have open.
  304.       -- (B) The same directory as the Cheat Engine .exe file, it you don't
  305.       --   have a cheat table open.
  306.       local stats_file = io.open("stats.txt", "w")
  307.       stats_file:write(stats_str)
  308.       stats_file:close()
  309.     end
  310.    
  311.     stats_current_frame = stats_current_frame + 1
  312.    
  313.   end
  314.  
  315.  
  316.   return 1
  317.  
  318. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement