daily pastebin goal
13%
SHARE
TWEET

Latest Modified init.lua

a guest Dec 22nd, 2018 4 in 55 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- license:BSD-3-Clause
  2. -- copyright-holders:Carl
  3. -- This includes a library of functions to be used at the Lua console as cf.getspaces() etc...
  4. local exports = {}
  5. exports.name = "cheatfind"
  6. exports.version = "0.0.1"
  7. exports.description = "Cheat finder helper library"
  8. exports.license = "The BSD 3-Clause License"
  9. exports.author = { name = "Carl" }
  10.  
  11. local cheatfind = exports
  12.  
  13. function cheatfind.startplugin()
  14.     local cheat = {}
  15.  
  16.     -- return table of devices and spaces
  17.     function cheat.getspaces()
  18.         local spaces = {}
  19.         for tag, device in pairs(manager:machine().devices) do
  20.             if device.spaces then
  21.                 spaces[tag] = {}
  22.                 for name, space in pairs(device.spaces) do
  23.                     spaces[tag][name] = space
  24.                 end
  25.             end
  26.         end
  27.         return spaces
  28.     end
  29.  
  30.     -- return table of ram devices
  31.     function cheat.getram()
  32.         local ram = {}
  33.         for tag, device in pairs(manager:machine().devices) do
  34.             if device:shortname() == "ram" then
  35.                 ram[tag] = {}
  36.                 ram[tag].dev = device
  37.                 ram[tag].size = emu.item(device.items["0/m_size"]):read(0)
  38.             end
  39.         end
  40.         return ram
  41.     end
  42.  
  43.     -- return table of share regions
  44.     function cheat.getshares()
  45.         local shares = {}
  46.         for tag, share in pairs(manager:machine():memory().shares) do
  47.             shares[tag] = share
  48.         end
  49.         return shares
  50.     end
  51.  
  52.     -- save data block
  53.     function cheat.save(space, start, size)
  54.         local data = { block = "", start = start, size = size, space = space, shift = 0 }
  55.         if getmetatable(space).__name:match("addr_space") then
  56.             data.shift = space.shift
  57.         end
  58.         if getmetatable(space).__name:match("device_t") then
  59.             if space:shortname() == "ram" then
  60.                 data.block = emu.item(space.items["0/m_pointer"]):read_block(start, size)
  61.                 if not data.block then
  62.                     return nil
  63.                 end
  64.             end
  65.         else
  66.             local block = ""
  67.             local temp = {}
  68.             local j = 1
  69.             if data.shift >= 0 then -- region or byte wide space
  70.                 for i = start, start + (size << data.shift), 1 << data.shift do
  71.                     if j < 65536 then
  72.                         temp[j] = string.pack("B", space:read_u8(i))
  73.                         j = j + 1
  74.                     else
  75.                         block = block .. table.concat(temp) .. string.pack("B", space:read_u8(i))
  76.                         temp = {}
  77.                         j = 1
  78.                     end
  79.                 end
  80.             elseif data.shift < 0 then
  81.                 local s = -data.shift
  82.                 local read = (s == 1) and space.read_u16 or (s == 2) and space.read_u32 or (s == 3) and space.read_u64 or space.read_u8
  83.                 local pack = (s == 1) and "<I2" or (s == 2) and "<I4" or (s == 3) and "<I8" or "B"
  84.                 for i = start, start + (size >> s) do
  85.                     if j < 65536 then
  86.                         temp[j] = string.pack(pack, read(space, i))
  87.                         j = j + 1
  88.                     else
  89.                         block = block .. table.concat(temp) .. string.pack(pack, read(space, i))
  90.                         temp = {}
  91.                         j = 1
  92.                     end
  93.                 end
  94.             end
  95.             block = block .. table.concat(temp)
  96.             data.block = block
  97.         end
  98.         return data
  99.     end
  100.  
  101.     -- compare two data blocks, format is as lua string.unpack, bne and beq val is table of masks, step is address increment value
  102.     function cheat.comp(newdata, olddata, oper, format, val, bcd, step)
  103.         local ret = {}
  104.         local ref = {} -- this is a helper for comparing two match lists
  105.         local bitmask = nil
  106.         if not step or step <= 0 then
  107.             step = 1
  108.         end
  109.  
  110.         local cfoper = {
  111.             lt = function(a, b, val) return (a < b and val == 0) or (val > 0 and (a + val) == b) end,
  112.             gt = function(a, b, val) return (a > b and val == 0) or (val > 0 and (a - val) == b) end,
  113.             eq = function(a, b, val) return a == b end,
  114.             ne = function(a, b, val) return (a ~= b and val == 0) or
  115.                 (val > 0 and ((a - val) == b or (a + val) == b)) end,
  116.             ltv = function(a, b, val) return a < val end,
  117.             gtv = function(a, b, val) return a > val end,
  118.             eqv = function(a, b, val) return a == val end,
  119.             nev = function(a, b, val) return a ~= val end }
  120.  
  121.         function cfoper.bne(a, b, val, addr)
  122.             if type(val) ~= "table" then
  123.                 bitmask = a ~ b
  124.                 return bitmask ~= 0
  125.             elseif not val[addr] then
  126.                 return false
  127.             else
  128.                 bitmask = (a ~ b) & val[addr]
  129.                 return bitmask ~= 0
  130.             end
  131.         end
  132.  
  133.         function cfoper.beq(a, b, val, addr)
  134.             if type(val) ~= "table" then
  135.                 bitmask = ~a ~ b
  136.                 return bitmask ~= 0
  137.             elseif not val[addr] then
  138.                 return false
  139.             else
  140.                 bitmask = (~a ~ b) & val[addr]
  141.                 return bitmask ~= 0
  142.             end
  143.         end
  144.  
  145.  
  146.         local function check_bcd(val)
  147.             local a = val + 0x0666666666666666
  148.             a = a ~ val
  149.             return (a & 0x1111111111111110) == 0
  150.         end
  151.  
  152.         local function frombcd(val)
  153.             local result = 0
  154.             local mul = 1
  155.             while val ~= 0 do
  156.                 result = result + ((val % 16) * mul)
  157.                 val = val >> 4
  158.                 mul = mul * 10
  159.             end
  160.             return result
  161.         end
  162.  
  163.         if not newdata and oper:sub(3, 3) == "v" then
  164.             newdata = olddata
  165.         end
  166.         if olddata.start ~= newdata.start or olddata.size ~= newdata.size or not cfoper[oper] then
  167.             return {}
  168.         end
  169.         if not val then
  170.             val = 0
  171.         end
  172.  
  173.         for i = 1, olddata.size, step do
  174.             local oldstat, old = pcall(string.unpack, format, olddata.block, i)
  175.             local newstat, new = pcall(string.unpack, format, newdata.block, i)
  176.             if oldstat and newstat then
  177.                 local oldc, newc = old, new
  178.                 local comp = false
  179.                 local addr = i - 1
  180.                 if olddata.shift ~= 0 then
  181.                     local s = olddata.shift
  182.                     addr = (s < 0) and addr >> -s or (s > 0) and addr << s
  183.                 end
  184.                 addr = addr + olddata.start
  185.                 if not bcd or (check_bcd(old) and check_bcd(new)) then
  186.                     if bcd then
  187.                         oldc = frombcd(old)
  188.                         newc = frombcd(new)
  189.                     end
  190.                     if cfoper[oper](newc, oldc, val, addr) then
  191.                         ret[#ret + 1] = { addr = addr,
  192.                         oldval = old,
  193.                         newval = new,
  194.                         bitmask = bitmask }
  195.                         ref[ret[#ret].addr] = #ret
  196.                     end
  197.                 end
  198.             end
  199.         end
  200.         return ret, ref
  201.     end
  202.  
  203.     local function check_val(oper, val, matches)
  204.         if oper ~= "beq" and oper ~= "bne" then
  205.             return val
  206.         elseif not matches or not matches[1].bitmask then
  207.             return nil
  208.         end
  209.         local masks = {}
  210.         for num, match in pairs(matches) do
  211.             masks[match.addr] = match.bitmask
  212.         end
  213.         return masks
  214.     end
  215.  
  216.     -- compare two blocks and filter by table of previous matches
  217.     function cheat.compnext(newdata, olddata, oldmatch, oper, format, val, bcd, step)
  218.         local matches, refs = cheat.comp(newdata, olddata, oper, format, check_val(oper, val, oldmatch), bcd, step)
  219.         local nonmatch = {}
  220.         local oldrefs = {}
  221.         for num, match in pairs(oldmatch) do
  222.             oldrefs[match.addr] = num
  223.         end
  224.         for addr, ref in pairs(refs) do
  225.             if not oldrefs[addr] then
  226.                 nonmatch[ref] = true
  227.                 refs[addr] = nil
  228.             else
  229.                 matches[ref].oldval = oldmatch[oldrefs[addr]].oldval
  230.             end
  231.         end
  232.         local resort = {}
  233.         for num, match in pairs(matches) do
  234.             if not nonmatch[num] then
  235.                 resort[#resort + 1] = match
  236.             end
  237.         end
  238.         return resort
  239.     end
  240.  
  241.  
  242.     -- compare a data block to the current state
  243.     function cheat.compcur(olddata, oper, format, val, bcd, step)
  244.         local newdata = cheat.save(olddata.space, olddata.start, olddata.size, olddata.space)
  245.         return cheat.comp(newdata, olddata, oper, format, val, bcd, step)
  246.     end
  247.  
  248.     -- compare a data block to the current state and filter
  249.     function cheat.compcurnext(olddata, oldmatch, oper, format, val, bcd, step)
  250.         local newdata = cheat.save(olddata.space, olddata.start, olddata.size, olddata.space)
  251.         return cheat.compnext(newdata, olddata, oldmatch, oper, format, val, bcd, step)
  252.     end
  253.  
  254.  
  255.     _G.cf = cheat
  256.  
  257.     local devtable = {}
  258.     local devsel = 1
  259.     local devcur = 1
  260.     local formtable = { " I1", " i1", "<I2", ">I2", "<i2", ">i2", "<I4", ">I4", "<i4", ">i4", "<I8", ">I8", "<i8", ">i8", }-- " <f", " >f", " <d", " >d" }
  261.     local formname = { "u8", "s8", "little u16", "big u16", "little s16", "big s16",
  262.                "little u32", "big u32", "little s32", "big s32", "little u64", "big u64", "little s64", "big s64", }
  263.                -- "little float", "big float", "little double", "big double" }
  264.     local width = 1
  265.     local bcd = 0
  266.     local align = 0
  267.     local optable = { "lt", "gt", "eq", "ne", "beq", "bne", "ltv", "gtv", "eqv", "nev" }
  268.     local opsel = 1
  269.     local value = 0
  270.     local leftop = 1
  271.     local rightop = 1
  272.     local leftop_text = "Slot 1"
  273.     local rightop_text = "Slot 1"
  274.     local value_text = ""
  275.     local expression_text = "Slot 1 < Slot 1"
  276.     local pausetable = { "Automatic", "Manual" }
  277.     local pausesel = 1
  278.     local matches = {}
  279.     local matchsel = 0
  280.     local matchpg = 0
  281.     local menu_blocks = {}
  282.     local watches = {}
  283.     local menu_func
  284.  
  285.     local cheat_save
  286.     local name = 1
  287.     local name_player = 1
  288.     local name_type = 1
  289.  
  290.     local function start()
  291.         devtable = {}
  292.         devsel = 1
  293.         devcur = 1
  294.         width = 1
  295.         bcd = 0
  296.         opsel = 1
  297.         value = 0
  298.         leftop = 1
  299.         rightop = 1
  300.         matches = {}
  301.         matchsel = 0
  302.         matchpg = 0
  303.         menu_blocks = {}
  304.         watches = {}
  305.  
  306.         local space_table = cheat.getspaces()
  307.         for tag, list in pairs(space_table) do
  308.             for name, space in pairs(list) do
  309.                 local ram = {}
  310.                 for num, entry in pairs(space.map) do
  311.                     if entry.writetype == "ram" then
  312.                         ram[#ram + 1] = { offset = entry.offset, size = entry.endoff - entry.offset }
  313.                         if space.shift > 0 then
  314.                             ram[#ram].size = ram[#ram].size >> space.shift
  315.                         elseif space.shift < 0 then
  316.                             ram[#ram].size = ram[#ram].size << -space.shift
  317.                         end
  318.                     end
  319.                 end
  320.                 if next(ram) then
  321.                     if tag == ":maincpu" and name == "program" then
  322.                         table.insert(devtable, 1, { name = tag .. ", " .. name, tag = tag, sname = name, space = space, ram = ram })
  323.                     else
  324.                         devtable[#devtable + 1] = { name = tag .. ", " .. name, tag = tag, sname = name, space = space, ram = ram }
  325.                     end
  326.                 end
  327.             end
  328.         end
  329.         space_table = cheat.getram()
  330.         for tag, ram in pairs(space_table) do
  331.             devtable[#devtable + 1] = { tag = tag, name = "ram", space = ram.dev, ram = {{ offset = 0, size = ram.size }} }
  332.         end
  333.         space_table = cheat.getshares()
  334.         for tag, share in pairs(space_table) do
  335.             devtable[#devtable + 1] = { tag = tag, name = tag, space = share, ram = {{ offset = 0, size = share.size }} }
  336.         end
  337.     end
  338.  
  339.     emu.register_start(start)
  340.    
  341.     local menu_is_showing = false
  342.     local tabbed_out = false
  343.    
  344.     local function menu_populate()
  345.         if pausesel == 1 then
  346.             emu.pause()
  347.             menu_is_showing = true
  348.         end
  349.         local menu = {}
  350.  
  351.         local function menu_prepare()
  352.             local menu_list = {}
  353.             menu_func = {}
  354.             for num, func in ipairs(menu) do
  355.                 local item, f = func()
  356.                 if item then
  357.                     menu_list[#menu_list + 1] = item
  358.                     menu_func[#menu_list] = f
  359.                 end
  360.             end
  361.             return menu_list
  362.         end
  363.  
  364.         local function menu_lim(val, min, max, menuitem)
  365.             if min == max then
  366.                 menuitem[3] = 0
  367.             elseif val == min then
  368.                 menuitem[3] = "r"
  369.             elseif val == max then
  370.                 menuitem[3] = "l"
  371.             else
  372.                 menuitem[3] = "lr"
  373.             end
  374.         end
  375.  
  376.         local function incdec(event, val, min, max)
  377.             local ret
  378.             if event == "left" and val ~= min then
  379.                 val = val - 1
  380.                 ret = true
  381.             elseif event == "right" and val ~= max then
  382.                 val = val + 1
  383.                 ret = true
  384.             end
  385.             return val, ret
  386.         end
  387.  
  388.         if cheat_save then
  389.             local cplayer = { "All", "P1", "P2", "P3", "P4" }
  390.             local ctype = { "Infinite Credits", "Infinite Time", "Infinite Lives", "Infinite Energy", "Infinite Ammo", "Infinite Bombs", "Invincibility" }
  391.             menu[#menu + 1] = function() return { _("Save Cheat"), "", "off" }, nil end
  392.             menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  393.             menu[#menu + 1] = function()
  394.                 local c = { _("Default"), _("Custom") }
  395.                 local m = { _("Cheat Name"), c[name], 0 }
  396.                 menu_lim(name, 1, #c, m)
  397.                 local function f(event)
  398.                     local r
  399.                     name, r = incdec(event, name, 1, #c)
  400.                     if (event == "select" or event == "comment") and name == 1 then
  401.                         manager:machine():popmessage(string.format(_("Default name is %s"), cheat_save.name))
  402.                     end
  403.                     return r
  404.                 end
  405.                 return m, f
  406.             end
  407.             if name == 2 then
  408.                 menu[#menu + 1] = function()
  409.                     local m = { _("Player"), cplayer[name_player], 0 }
  410.                     menu_lim(name_player, 1, #cplayer, m)
  411.                     return m, function(event) local r name_player, r = incdec(event, name_player, 1, #cplayer) return r end
  412.                 end
  413.                 menu[#menu + 1] = function()
  414.                     local m = { _("Type"), ctype[name_type], 0 }
  415.                     menu_lim(name_type, 1, #ctype, m)
  416.                     return m, function(event) local r name_type, r = incdec(event, name_type, 1, #ctype) return r end
  417.                 end
  418.             end
  419.             menu[#menu + 1] = function()
  420.                 local m = { _("Save"), "", 0 }
  421.                 local function f(event)
  422.                     if event == "select" then
  423.                         local desc
  424.                         local written = false
  425.                         if name == 2 then
  426.                             if cplayer[name_player] == "All" then
  427.                                 desc = ctype[name_type]
  428.                             else
  429.                                 desc = cplayer[name_player] .. " " .. ctype[name_type]
  430.                             end
  431.                         else
  432.                             desc = cheat_save.name
  433.                         end
  434.                         local filename = cheat_save.filename .. "_" .. desc
  435.                         local file = io.open(filename .. ".json", "w")
  436.                         if file then
  437.                             file:write(string.format(cheat_save.json, desc))
  438.                             file:close()
  439.                             -- xml or simple are program space only
  440.                             if not getmetatable(devtable[devcur].space).__name:match("device_t") and devtable[devcur].sname == "program" then
  441.                                 file = io.open(filename .. ".xml", "w")
  442.                                 file:write(string.format(cheat_save.xml, desc))
  443.                                 file:close()
  444.                                 file = io.open(cheat_save.path .. "/cheat.simple", "a")
  445.                                 file:write(string.format(cheat_save.simple, desc))
  446.                                 -- old cheat .dat format, write support only and defaults to setting all type bits to 0
  447.                                 file:write(string.format(cheat_save.dat, desc))
  448.                                 file:close()
  449.                                 manager:machine():popmessage(string.format(_("Cheat written to %s and added to cheat.simple"), filename))
  450.                             end
  451.                             written = true
  452.                         elseif not getmetatable(devtable[devcur].space).__name:match("device_t") and devtable[devcur].sname == "program" then
  453.                             file = io.open(cheat_save.path .. "/cheat.simple", "a")
  454.                             if file then
  455.                                 file:write(string.format(cheat_save.simple, desc))
  456.                                 file:close()
  457.                                 manager:machine():popmessage(_("Cheat added to cheat.simple"))
  458.                                 written = true
  459.                             end
  460.                         end
  461.                         if not written then
  462.                             manager:machine():popmessage(_("Unable to write file\nEnsure that cheatpath folder exists"))
  463.                         end
  464.                         cheat_save = nil
  465.                         return true
  466.                     end
  467.                     return false
  468.                 end
  469.                 return m, f
  470.             end
  471.             menu[#menu + 1] = function() return { _("Cancel"), "", 0 }, function(event) if event == "select" then cheat_save = nil return true end end end
  472.             return menu_prepare()
  473.         end
  474.  
  475.         menu[#menu + 1] = function()
  476.             local m = { _("CPU or RAM"), devtable[devsel].name, 0 }
  477.             menu_lim(devsel, 1, #devtable, m)
  478.             local function f(event)
  479.                 if (event == "left" or event == "right") and #menu_blocks ~= 0 then
  480.                     manager:machine():popmessage(_("Changes to this only take effect when \"Start new search\" is selected"))
  481.                 end
  482.                 devsel = incdec(event, devsel, 1, #devtable)
  483.                 return true
  484.             end
  485.             return m, f
  486.         end
  487.  
  488.         menu[#menu + 1] = function()
  489.             local m = { _("Pause Mode"), pausetable[pausesel], 0 }
  490.             menu_lim(pausesel, 1, pausetable, m)
  491.             local function f(event)
  492.                 if (event == "left" or event == "right") then                  
  493.                     if pausesel == 1 then
  494.                         pausesel = 2
  495.                         menu_is_showing = false
  496.                         manager:machine():popmessage(_("Manually pause & unpause the game when needed with the pause hotkey"))
  497.                     else
  498.                         pausesel = 1
  499.                         emu.pause()
  500.                     end
  501.                 end
  502.  
  503.                 return true
  504.             end
  505.             return m, f        
  506.         end    
  507.        
  508.         menu[#menu + 1] = function()
  509.             local function f(event)
  510.                 local ret = false
  511.                 if event == "select" then
  512.                     menu_blocks = {}
  513.                     matches = {}
  514.                     devcur = devsel
  515.                     for num, region in ipairs(devtable[devcur].ram) do
  516.                         menu_blocks[num] = {}
  517.                         menu_blocks[num][1] = cheat.save(devtable[devcur].space, region.offset, region.size)
  518.                     end
  519.                     manager:machine():popmessage(_("All slots cleared and current state saved to Slot 1"))
  520.                     watches = {}
  521.                     opsel = 1
  522.                     value = 0
  523.                     leftop = 1
  524.                     rightop = 1
  525.                     leftop_text = "Slot 1"
  526.                     rightop_text = "Slot 1"
  527.                     value_text = ""
  528.                     expression_text = "Slot 1 < Slot 1"                        
  529.                     matchsel = 0
  530.                     return true
  531.                 end
  532.             end
  533.                 local opsel = 1
  534.             return { _("Start new search"), "", 0 }, f
  535.         end
  536.        
  537.  
  538.        
  539.         if #menu_blocks ~= 0 then
  540.             menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  541.             menu[#menu + 1] = function()
  542.                 local function f(event)
  543.                     if event == "select" then
  544.                         for num, region in ipairs(devtable[devcur].ram) do
  545.                             menu_blocks[num][#menu_blocks[num] + 1] = cheat.save(devtable[devcur].space, region.offset, region.size)
  546.                         end
  547.                         manager:machine():popmessage(_("Memory State saved to Slot ").. #menu_blocks[1])
  548.                         if (leftop == #menu_blocks[1] - 1 and rightop == #menu_blocks[1] - 2 ) then
  549.                             leftop = #menu_blocks[1]
  550.                             rightop = #menu_blocks[1]-1
  551.                         elseif (leftop == #menu_blocks[1] - 2 and rightop == #menu_blocks[1] - 1 ) then
  552.                             leftop = #menu_blocks[1]-1
  553.                             rightop = #menu_blocks[1]
  554.                         elseif (leftop == #menu_blocks[1] - 1 ) then
  555.                             leftop = #menu_blocks[1]
  556.                         elseif (rightop == #menu_blocks[1] - 1) then   
  557.                             rightop = #menu_blocks[1]
  558.                         end
  559.                         devsel = devcur
  560.                         return true
  561.                     end
  562.                 end
  563.                 return { _("Save Current Memory State to Slot ") .. #menu_blocks[1] + 1, "", 0 }, f
  564.             end
  565.             menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  566.             menu[#menu + 1] = function()
  567.                 local function f(event)
  568.                     if event == "select" then
  569.                         local count = 0
  570.                         local step = align == 1 and formtable[width]:sub(3, 3) or "1"
  571.                         if step == "f" then
  572.                             step = 4
  573.                         elseif step == "d" then
  574.                             step = 8
  575.                         else
  576.                             step = tonumber(step)
  577.                         end
  578.                         if #matches == 0 then
  579.                             matches[1] = {}
  580.                             for num = 1, #menu_blocks do
  581.                                 matches[1][num] = cheat.comp(menu_blocks[num][leftop], menu_blocks[num][rightop],
  582.                                 optable[opsel], formtable[width], value, bcd == 1, step)
  583.                                 count = count + #matches[1][num]
  584.                             end
  585.                         else
  586.                             lastmatch = matches[#matches]
  587.                             matches[#matches + 1] = {}
  588.                             for num = 1, #menu_blocks do
  589.                                 matches[#matches][num] = cheat.compnext(menu_blocks[num][leftop], menu_blocks[num][rightop],
  590.                                 lastmatch[num], optable[opsel], formtable[width], value, bcd == 1, step)
  591.                                 count = count + #matches[#matches][num]
  592.                             end
  593.                         end
  594.                         manager:machine():popmessage(string.format(_("%d total matches found"), count))
  595.                         matches[#matches].count = count
  596.                         matchpg = 0
  597.                         devsel = devcur
  598.                         return true
  599.                     end
  600.                 end
  601.                
  602.                 if optable[opsel] == "lt" then
  603.                     if (value == 0 ) then
  604.                         expression_text = leftop_text .. " < " .. rightop_text
  605.                     else
  606.                         expression_text = leftop_text .. " + " .. value .. " == " .. rightop_text
  607.                     end
  608.                 elseif optable[opsel] == "gt" then
  609.                     if (value == 0 ) then
  610.                         expression_text = leftop_text .. " > " .. rightop_text
  611.                     else
  612.                         expression_text = leftop_text .. " - " .. value .. " == " .. rightop_text
  613.                     end
  614.                 elseif optable[opsel] == "eq" then
  615.                     expression_text = leftop_text .. " == " .. rightop_text
  616.                 elseif optable[opsel] == "ne" then
  617.                     if (value == 0 ) then
  618.                         expression_text = leftop_text .. " != " .. rightop_text
  619.                     else
  620.                         expression_text = leftop_text .. " == " .. rightop_text .. " +/- " .. value
  621.                     end
  622.                 elseif optable[opsel] == "beq" then
  623.                     expression_text = leftop_text .. " BITWISE== " .. rightop_text
  624.                 elseif optable[opsel] == "bne" then
  625.                     expression_text = leftop_text .. " BITWISE!= " .. rightop_text
  626.                 elseif optable[opsel] == "ltv" then
  627.                     expression_text = leftop_text .. " < " .. value
  628.                 elseif optable[opsel] == "gtv" then
  629.                     expression_text = leftop_text .. " > " .. value
  630.                 elseif optable[opsel] == "eqv" then
  631.                     expression_text = leftop_text .. " == " .. value
  632.                 elseif optable[opsel] == "nev" then
  633.                     expression_text = leftop_text .. " != " .. value
  634.                 end    
  635.                 return { _("Perform Compare  :  ") .. expression_text, "", 0 }, f
  636.             end
  637.             menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  638.             menu[#menu + 1] = function()
  639.                 local m = { _(leftop), "", 0 }
  640.                 menu_lim(leftop, 1, #menu_blocks[1], m)
  641.                 m[1] = "Slot " .. leftop
  642.                 return m, function(event) local r leftop, r = incdec(event, leftop, 1, #menu_blocks[1]) leftop_text = "Slot " .. leftop return r end
  643.             end
  644.             menu[#menu + 1] = function()
  645.                 local m = { _(optable[opsel]), "", 0 }
  646.                 menu_lim(opsel, 1, #optable, m)
  647.                 local function f(event)
  648.                     local r
  649.                     opsel, r = incdec(event, opsel, 1, #optable)
  650.                     if event == "left" or event == "right" or event == "comment" then
  651.                         if optable[opsel] == "lt" then
  652.                             manager:machine():popmessage(_("Left less than right, value is difference"))
  653.                         elseif optable[opsel] == "gt" then
  654.                             manager:machine():popmessage(_("Left greater than right, value is difference"))
  655.                         elseif optable[opsel] == "eq" then
  656.                             manager:machine():popmessage(_("Left equal to right"))
  657.                         elseif optable[opsel] == "ne" then
  658.                             manager:machine():popmessage(_("Left not equal to right, value is difference"))
  659.                         elseif optable[opsel] == "beq" then
  660.                             manager:machine():popmessage(_("Left equal to right with bitmask"))
  661.                         elseif optable[opsel] == "bne" then
  662.                             manager:machine():popmessage(_("Left not equal to right with bitmask"))
  663.                         elseif optable[opsel] == "ltv" then
  664.                             manager:machine():popmessage(_("Left less than value"))
  665.                         elseif optable[opsel] == "gtv" then
  666.                             manager:machine():popmessage(_("Left greater than value"))
  667.                         elseif optable[opsel] == "eqv" then
  668.                             manager:machine():popmessage(_("Left equal to value"))
  669.                         elseif optable[opsel] == "nev" then
  670.                             manager:machine():popmessage(_("Left not equal to value"))
  671.                         end
  672.                     end
  673.                     return r
  674.                 end
  675.                 return m, f
  676.             end
  677.             menu[#menu + 1] = function()
  678.                 if optable[opsel]:sub(3, 3) == "v" then
  679.                     return nil
  680.                 end
  681.                 local m = { _(rightop), "", 0 }
  682.                 menu_lim(rightop, 1, #menu_blocks[1], m)
  683.                 m[1] = "Slot " .. rightop
  684.                 return m, function(event) local r rightop, r = incdec(event, rightop, 1, #menu_blocks[1]) rightop_text = "Slot " .. rightop return r end
  685.             end
  686.             menu[#menu + 1] = function()
  687.                 if optable[opsel] == "bne" or optable[opsel] == "beq" or optable[opsel] == "eq" then
  688.                     return nil
  689.                 end
  690.                 local m = { _("Value"), value, "" }
  691.                 local max = 100 -- max value?
  692.                 menu_lim(value, 0, max, m)
  693.                 if value == 0 and optable[opsel]:sub(3, 3) ~= "v" then
  694.                     m[2] = _("Any")
  695.                 end
  696.                 return m, function(event) local r value, r = incdec(event, value, 0, max) return r end
  697.             end
  698.             menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  699.             menu[#menu + 1] = function()
  700.                 local m = { _("Data Format"), formname[width], 0 }
  701.                 menu_lim(width, 1, #formtable, m)
  702.                 return m, function(event) local r width, r = incdec(event, width, 1, #formtable) return r end
  703.             end
  704.             menu[#menu + 1] = function()
  705.                 if optable[opsel] == "bne" or optable[opsel] == "beq" then
  706.                     return nil
  707.                 end
  708.                 local m = { "BCD", _("Off"), 0 }
  709.                 menu_lim(bcd, 0, 1, m)
  710.                 if bcd == 1 then
  711.                     m[2] = _("On")
  712.                 end
  713.                 return m, function(event) local r bcd, r = incdec(event, bcd, 0, 1) return r end
  714.             end
  715.             menu[#menu + 1] = function()
  716.                 if formtable[width]:sub(3, 3) == "1" then
  717.                     return nil
  718.                 end
  719.                 local m = { "Aligned only", _("Off"), 0 }
  720.                 menu_lim(align, 0, 1, m)
  721.                 if align == 1 then
  722.                     m[2] = _("On")
  723.                 end
  724.                 return m, function(event) local r align, r = incdec(event, align, 0, 1) return r end
  725.             end
  726.             if #matches ~= 0 then
  727.                 menu[#menu + 1] = function()
  728.                     local function f(event)
  729.                         if event == "select" then
  730.                             matches[#matches] = nil
  731.                             matchpg = 0
  732.                             return true
  733.                         end
  734.                     end
  735.                     return { _("Undo last search -- #") .. #matches, "", 0 }, f
  736.                 end
  737.                 menu[#menu + 1] = function() return { "---", "", "off" }, nil end
  738.                 menu[#menu + 1] = function()
  739.                     local m = { _("Match block"), matchsel, "" }
  740.                     menu_lim(matchsel, 0, #matches[#matches], m)
  741.                     if matchsel == 0 then
  742.                         m[2] = _("All")
  743.                     end
  744.                     local function f(event)
  745.                         local r
  746.                         matchsel, r = incdec(event, matchsel, 0, #matches[#matches])
  747.                         if r then
  748.                             matchpg = 0
  749.                         end
  750.                         return r
  751.                     end
  752.                     return m, f
  753.                 end
  754.                 local function mpairs(sel, list, start)
  755.                     if #list == 0 then
  756.                         return function() end, nil, nil
  757.                     end
  758.                     if sel ~= 0 then
  759.                         list = {list[sel]}
  760.                     end
  761.                     local function mpairs_it(list, i)
  762.                         local match
  763.                         i = i + 1
  764.                         local sel = i + start
  765.                         for j = 1, #list do
  766.                             if sel <= #list[j] then
  767.                                 match = list[j][sel]
  768.                                 break
  769.                             else
  770.                                 sel = sel - #list[j]
  771.                             end
  772.                         end
  773.                         if not match then
  774.                             return
  775.                         end
  776.                         return i, match
  777.                     end
  778.                     return mpairs_it, list, 0
  779.                 end
  780.                 local bitwidth = formtable[width]:sub(3, 3)
  781.                 if bitwidth == "2" then
  782.                     bitwidth = " %04x"
  783.                 elseif bitwidth == "4" then
  784.                     bitwidth = " %08x"
  785.                 elseif bitwidth == "8" then
  786.                     bitwidth = " %016x"
  787.                 elseif bitwidth == "f" or bitwidth == "d" then
  788.                     bitwidth = " %010f"
  789.                 else
  790.                     bitwidth = " %02x"
  791.                 end
  792.  
  793.                 local function match_exec(match)
  794.                     local dev = devtable[devcur]
  795.                     local cheat = { desc = string.format(_("Test cheat at addr %08X"), match.addr), script = {} }
  796.                     local wid = formtable[width]:sub(3, 3)
  797.                     local widchar
  798.                     local form
  799.                     if wid == "2" then
  800.                         wid = "u16"
  801.                         form = "%08x %04x"
  802.                         widchar = "w"
  803.                     elseif wid == "4" then
  804.                         wid = "u32"
  805.                         form = "%08x %08x"
  806.                         widchart = "d"
  807.                     elseif wid == "8" then
  808.                         wid = "u64"
  809.                         form = "%08x %016x"
  810.                         widchar = "q"
  811.                     elseif wid == "f" then
  812.                         wid = "u32"
  813.                         form = "%08x %f"
  814.                         widchar = "d"
  815.                     elseif wid == "d" then
  816.                         wid = "u64"
  817.                         form = "%08x %f"
  818.                         widchar = "q"
  819.                     else
  820.                         wid = "u8"
  821.                         form = "%08x %02x"
  822.                         widchar = "b"
  823.                     end
  824.  
  825.  
  826.                     if getmetatable(dev.space).__name:match("device_t") then
  827.                         cheat.ram = { ram = dev.tag }
  828.                         cheat.script.run = "ram:write(" .. match.addr .. "," .. match.newval .. ")"
  829.                     elseif getmetatable(dev.space).__name:match("memory_share") then
  830.                         cheat.share = { share = dev.tag }
  831.                         cheat.script.run = "share:write_" .. wid .. "(" .. match.addr .. "," .. match.newval .. ")"
  832.                     else
  833.                         cheat.space = { cpu = { tag = dev.tag, type = dev.sname } }
  834.                         cheat.script.run = "cpu:write_" .. wid .. "(" .. match.addr .. "," .. match.newval .. ")"
  835.                     end
  836.                     if match.mode == 1 then
  837.                         if not _G.ce then
  838.                             manager:machine():popmessage(_("Cheat engine not available"))
  839.                         else
  840.                             _G.ce.inject(cheat)
  841.                         end
  842.                     elseif match.mode == 2 then
  843.                         cheat_save = {}
  844.                         menu = 1
  845.                         menu_player = 1
  846.                         menu_type = 1
  847.                         local setname = emu.romname()
  848.                         if emu.softname() ~= "" then
  849.                             if emu.softname():find(":") then
  850.                                 filename = emu.softname():gsub(":", "/")
  851.                             else
  852.                                 for name, image in pairs(manager:machine().images) do
  853.                                     if image:exists() and image:software_list_name() ~= "" then
  854.                                         setname = image:software_list_name() .. "/" .. emu.softname()
  855.                                     end
  856.                                 end
  857.                             end
  858.                         end
  859.                         -- lfs.env_replace is defined in boot.lua
  860.                         cheat_save.path = lfs.env_replace(manager:machine():options().entries.cheatpath:value()):match("([^;]+)")
  861.                         cheat_save.filename = string.format("%s/%s", cheat_save.path, setname)
  862.                         cheat_save.name = cheat.desc
  863.                         local json = require("json")
  864.                         cheat.desc = "%s"
  865.                         cheat_save.json = json.stringify({[1] = cheat}, {indent = true})
  866.                         cheat_save.xml = string.format("<mamecheat version=\"1\">\n<cheat desc=\"%%s\">\n<script state=\"run\">\n<action>%s.p%s@%X=%X</action>\n</script>\n</cheat>\n</mamecheat>", dev.tag:sub(2), widchar, match.addr, match.newval)
  867.                         cheat_save.simple = string.format("%s,%s,%X,%s,%X,%%s\n", setname, dev.tag, match.addr, widchar, match.newval)
  868.                         cheat_save.dat = string.format(":%s:00000000:%X:%08X:FFFFFFFF:%%s\n", setname,  match.addr, match.newval)          
  869.                         manager:machine():popmessage(string.format(_("Default name is %s"), cheat_save.name))
  870.                         return true
  871.                     else
  872.                         local func = "return space:read"
  873.                         local env = { space = devtable[devcur].space }
  874.                         if not getmetatable(dev.space).__name:match("device_t") then
  875.                             func = func .. "_" .. wid
  876.                         end
  877.                         func = func .. "(" .. match.addr .. ")"
  878.                         watches[#watches + 1] = { addr = match.addr, func = load(func, func, "t", env), format = form }
  879.                         return true
  880.                     end
  881.                     return false
  882.                 end
  883.  
  884.                 for num2, match in mpairs(matchsel, matches[#matches], matchpg * 100) do
  885.                     if num2 > 100 then
  886.                         break
  887.                     end
  888.                     menu[#menu + 1] = function()
  889.                         if not match.mode then
  890.                             match.mode = 1
  891.                         end
  892.                         local modes = { _("Test"), _("Write"), _("Watch") }
  893.                         local m = { string.format("%08x" .. bitwidth .. bitwidth, match.addr, match.oldval,
  894.                                                       match.newval), modes[match.mode], 0 }
  895.                         menu_lim(match.mode, 1, #modes, m)
  896.                         local function f(event)
  897.                             local r
  898.                             match.mode, r = incdec(event, match.mode, 1, 3)
  899.                             if event == "select" then
  900.                                 r = match_exec(match)
  901.                             end
  902.                             return r
  903.                         end
  904.                         return m, f
  905.                     end
  906.                 end
  907.                 if matches[#matches].count > 100 then
  908.                     menu[#menu + 1] = function()
  909.                         local m = { _("Page"), matchpg, 0 }
  910.                         local max
  911.                         if matchsel == 0 then
  912.                             max = math.ceil(matches[#matches].count / 100)
  913.                         else
  914.                             max = #matches[#matches][matchsel]
  915.                         end
  916.                         menu_lim(matchpg, 0, max, m)
  917.                         local function f(event)
  918.                             matchpg, r = incdec(event, matchpg, 0, max)
  919.                             return r
  920.                         end
  921.                         return m, f
  922.                     end
  923.                 end
  924.             end
  925.             if #watches ~= 0 then
  926.                 menu[#menu + 1] = function()
  927.                     return { _("Clear Watches"), "", 0 }, function(event) if event == "select" then watches = {} return true end end
  928.                 end
  929.             end
  930.         end
  931.         return menu_prepare()
  932.     end
  933.  
  934.     local function menu_callback(index, event)
  935.         if event == "cancel" and pausesel == 1 then
  936.             emu.unpause()
  937.             menu_is_showing = false
  938.             return {0,0,0}
  939.         end
  940.         return menu_func[index](event)
  941.     end
  942.     emu.register_menu(menu_callback, menu_populate, _("Cheat Finder"))
  943.     emu.register_frame_done(function ()
  944.             local tag, screen = next(manager:machine().screens)
  945.             local height = mame_manager:ui():get_line_height()
  946.             for num, watch in ipairs(watches) do
  947.                 screen:draw_text("left", num * height, string.format(watch.format, watch.addr, watch.func()))
  948.             end        
  949.             if tabbed_out and manager:ui():is_menu_active()  then
  950.                 emu.pause()
  951.                 menu_is_showing = true
  952.                 tabbed_out = false
  953.             end                
  954.         end)
  955.     emu.register_periodic(function ()
  956.         if menu_is_showing and not manager:ui():is_menu_active() then
  957.             emu.unpause()
  958.             menu_is_showing = false
  959.             tabbed_out = true
  960.         end
  961.     end)   
  962. end
  963.  
  964. return exports
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