diff options
author | 2019-02-04 21:59:31 +0000 | |
---|---|---|
committer | 2019-02-04 21:59:31 +0000 | |
commit | 87e633e039e006ac3a90210f324b1fd996065fa0 (patch) | |
tree | 4d1be8606427448885c5c13b5d36e0311b64c546 /plugins/cheatfind | |
parent | 24e192fc86f7b876e28a9214a4d84e70ac57c18b (diff) |
Cheat Finder Usability Improvements
1. Changes visual indications to make it nicer & quicker to use.
2. Adds selectable automatic pause capability to the cheat finder menu.
3. Allows the Test/Write poke to be changed
4. Adds another cheat format capability for cheat.simple (write support only)
Diffstat (limited to 'plugins/cheatfind')
-rw-r--r-- | plugins/cheatfind/init.lua | 334 |
1 files changed, 282 insertions, 52 deletions
diff --git a/plugins/cheatfind/init.lua b/plugins/cheatfind/init.lua index 5dcdd5a18e3..dd09da404a7 100644 --- a/plugins/cheatfind/init.lua +++ b/plugins/cheatfind/init.lua @@ -109,7 +109,6 @@ function cheatfind.startplugin() if (olddata.shift < 0) and (step < (1 << -olddata.shift)) then step = 1 << -olddata.shift; end - local cfoper = { lt = function(a, b, val) return (a < b and val == 0) or (val > 0 and (a + val) == b) end, gt = function(a, b, val) return (a > b and val == 0) or (val > 0 and (a - val) == b) end, @@ -260,18 +259,35 @@ function cheatfind.startplugin() local devtable = {} local devsel = 1 local devcur = 1 - local formtable = { " I1", " i1", "<I2", ">I2", "<i2", ">i2", "<I4", ">I4", "<i4", ">i4", "<I8", ">I8", "<i8", ">i8", }-- " <f", " >f", " <d", " >d" } - local formname = { "u8", "s8", "little u16", "big u16", "little s16", "big s16", - "little u32", "big u32", "little s32", "big s32", "little u64", "big u64", "little s64", "big s64", } - -- "little float", "big float", "little double", "big double" } + + + --local formtable = { " I1", " i1", "<I2", ">I2", "<i2", ">i2", "<I4", ">I4", "<i4", ">i4", "<I8", ">I8", "<i8", ">i8", }-- " <f", " >f", " <d", " >d" } + --local formname = { "u8", "s8", "little u16", "big u16", "little s16", "big s16", + -- "little u32", "big u32", "little s32", "big s32", "little u64", "big u64", "little s64", "big s64", } + -- -- "little float", "big float", "little double", "big double" } + -- Reordered into likelyhood of use order: unsigned byte by big endian unsigned by little endian unsigned then unsigned in same order + local formtable = { " I1", ">I2", ">I4", ">I8", "<I2", "<I4", "<I8", " i1", ">i2", ">i4", ">i8", "<i2", "<i4", "<i8", }-- " <f", " >f", " <d", " >d" } + local formname = { "u8", "big u16", "big u32", "big u64", "little u16", "little u32", + "little u64", "s8", "big s16", "big s32", "big s64", "little s16", "little s32", "little s64", } + local width = 1 local bcd = 0 local align = 0 local optable = { "lt", "gt", "eq", "ne", "beq", "bne", "ltv", "gtv", "eqv", "nev" } local opsel = 1 local value = 0 - local leftop = 2 + local leftop = 1 local rightop = 1 + local leftop_text = "Slot 1" + local rightop_text = "Slot 1" + local value_text = "" + local expression_text = "Slot 1 < Slot 1" + local pausetable = { "Automatic", "Manual" } + local pausesel = 1 + local pokevaltable = { "Slot 1 Value", "Last Slot Value", "0x00", "0x01", "0x02", "0x03", "0x04", "0x05", "0x06", "0x07", "0x08", "0x09", "0x63 (Decimal 99)", "0x99 (BCD 99)", + "0xFF (Decimal 255)" , "0x3E7 (Decimal 999)", "0x999 (BCD 999)", "0x270F (Decimal 9999)", "0x9999 (BCD 9999)", "0xFFFF (Decimal 65535)" } + local pokevalsel = 1 + local matches = {} local matchsel = 0 local matchpg = 0 @@ -292,7 +308,7 @@ function cheatfind.startplugin() bcd = 0 opsel = 1 value = 0 - leftop = 2 + leftop = 1 rightop = 1 matches = {} matchsel = 0 @@ -334,8 +350,15 @@ function cheatfind.startplugin() end emu.register_start(start) - + + local menu_is_showing = false + local tabbed_out = false + local function menu_populate() + if pausesel == 1 then + emu.pause() + menu_is_showing = true + end local menu = {} local function menu_prepare() @@ -433,6 +456,8 @@ function cheatfind.startplugin() file:close() file = io.open(cheat_save.path .. "/cheat.simple", "a") file:write(string.format(cheat_save.simple, desc)) + -- old cheat .dat format, write support only (for cheat forum posting of new cheats if posted in simple format) + file:write(string.format(cheat_save.dat, desc)) file:close() manager:machine():popmessage(string.format(_("Cheat written to %s and added to cheat.simple"), filename)) end @@ -441,6 +466,8 @@ function cheatfind.startplugin() file = io.open(cheat_save.path .. "/cheat.simple", "a") if file then file:write(string.format(cheat_save.simple, desc)) + -- old cheat .dat format, write support only (for cheat forum posting of new cheats if posted in simple format) + file:write(string.format(cheat_save.dat, desc)) file:close() manager:machine():popmessage(_("Cheat added to cheat.simple")) written = true @@ -474,6 +501,28 @@ function cheatfind.startplugin() end menu[#menu + 1] = function() + local m = { _("Pause Mode"), pausetable[pausesel], 0 } + menu_lim(pausesel, 1, pausetable, m) + local function f(event) + if (event == "left" or event == "right") then + if pausesel == 1 then + pausesel = 2 + menu_is_showing = false + manager:machine():popmessage(_("Manually pause & unpause the game when needed with the pause hotkey")) + else + pausesel = 1 + emu.pause() + end + end + + return true + end + return m, f + end + + + + menu[#menu + 1] = function() local function f(event) local ret = false if event == "select" then @@ -484,16 +533,26 @@ function cheatfind.startplugin() menu_blocks[num] = {} menu_blocks[num][1] = cheat.save(devtable[devcur].space, region.offset, region.size) end - manager:machine():popmessage(_("Data cleared and current state saved")) + manager:machine():popmessage(_("All slots cleared and current state saved to Slot 1")) watches = {} - leftop = 2 + opsel = 1 + value = 0 + leftop = 1 rightop = 1 + leftop_text = "Slot 1" + rightop_text = "Slot 1" + value_text = "" + expression_text = "Slot 1 < Slot 1" matchsel = 0 return true end end + local opsel = 1 return { _("Start new search"), "", 0 }, f end + + + if #menu_blocks ~= 0 then menu[#menu + 1] = function() return { "---", "", "off" }, nil end menu[#menu + 1] = function() @@ -502,15 +561,28 @@ function cheatfind.startplugin() for num, region in ipairs(devtable[devcur].ram) do menu_blocks[num][#menu_blocks[num] + 1] = cheat.save(devtable[devcur].space, region.offset, region.size) end - manager:machine():popmessage(_("Current state saved")) - leftop = (leftop == #menu_blocks[1]) and #menu_blocks[1] + 1 or leftop - rightop = (rightop == #menu_blocks[1] - 1) and #menu_blocks[1] or rightop + manager:machine():popmessage(string.format(_("Memory State saved to Slot %d"), #menu_blocks[1])) + + if (leftop == #menu_blocks[1] - 1 and rightop == #menu_blocks[1] - 2 ) then + leftop = #menu_blocks[1] + rightop = #menu_blocks[1]-1 + elseif (leftop == #menu_blocks[1] - 2 and rightop == #menu_blocks[1] - 1 ) then + leftop = #menu_blocks[1]-1 + rightop = #menu_blocks[1] + elseif (leftop == #menu_blocks[1] - 1 ) then + leftop = #menu_blocks[1] + elseif (rightop == #menu_blocks[1] - 1) then + rightop = #menu_blocks[1] + end + leftop_text = string.format("Slot %d", leftop) + rightop_text = string.format("Slot %d", rightop) devsel = devcur return true end end - return { _("Save current -- #") .. #menu_blocks[1] + 1, "", 0 }, f + return { _("Save Current Memory State to Slot ") .. #menu_blocks[1] + 1, "", 0 }, f end + menu[#menu + 1] = function() return { "---", "", "off" }, nil end menu[#menu + 1] = function() local function f(event) if event == "select" then @@ -526,26 +598,16 @@ function cheatfind.startplugin() if #matches == 0 then matches[1] = {} for num = 1, #menu_blocks do - if leftop == #menu_blocks[1] + 1 then - matches[1][num] = cheat.compcur(menu_blocks[num][rightop], optable[opsel], - formtable[width], value, bcd == 1, step) - else - matches[1][num] = cheat.comp(menu_blocks[num][leftop], menu_blocks[num][rightop], - optable[opsel], formtable[width], value, bcd == 1, step) - end + matches[1][num] = cheat.comp(menu_blocks[num][leftop], menu_blocks[num][rightop], + optable[opsel], formtable[width], value, bcd == 1, step) count = count + #matches[1][num] end else lastmatch = matches[#matches] matches[#matches + 1] = {} for num = 1, #menu_blocks do - if leftop == #menu_blocks[1] + 1 then - matches[#matches][num] = cheat.compcurnext(menu_blocks[num][rightop], lastmatch[num], - optable[opsel], formtable[width], value, bcd == 1, step) - else - matches[#matches][num] = cheat.compnext(menu_blocks[num][leftop], menu_blocks[num][rightop], - lastmatch[num], optable[opsel], formtable[width], value, bcd == 1, step) - end + matches[#matches][num] = cheat.compnext(menu_blocks[num][leftop], menu_blocks[num][rightop], + lastmatch[num], optable[opsel], formtable[width], value, bcd == 1, step) count = count + #matches[#matches][num] end end @@ -556,31 +618,64 @@ function cheatfind.startplugin() return true end end - return { _("Compare"), "", 0 }, f + + if optable[opsel] == "lt" then + if (value == 0 ) then + expression_text = string.format("%s < %s", leftop_text, rightop_text) + else + expression_text = string.format("%s == %s - %d", leftop_text, rightop_text, value) + end + elseif optable[opsel] == "gt" then + if (value == 0 ) then + expression_text = string.format("%s > %s", leftop_text, rightop_text) + else + expression_text = string.format("%s == %s + %d", leftop_text, rightop_text, value) + end + elseif optable[opsel] == "eq" then + expression_text = string.format("%s == %s", leftop_text, rightop_text) + elseif optable[opsel] == "ne" then + if (value == 0 ) then + expression_text = string.format("%s != %s", leftop_text, rightop_text) + else + expression_text = string.format("%s == %s +/- %d", leftop_text, rightop_text, value) + end + elseif optable[opsel] == "beq" then + expression_text = string.format("%s BITWISE== %s", leftop_text, rightop_text) + elseif optable[opsel] == "bne" then + expression_text = string.format("%s BITWISE!= %s", leftop_text, rightop_text) + elseif optable[opsel] == "ltv" then + expression_text = string.format("%s < %d", leftop_text, value) + elseif optable[opsel] == "gtv" then + expression_text = string.format("%s > %d", leftop_text, value) + elseif optable[opsel] == "eqv" then + expression_text = string.format("%s == %d", leftop_text, value) + elseif optable[opsel] == "nev" then + string.format("%s != %d", leftop_text, value) + end + return { _("Perform Compare : ") .. expression_text, "", 0 }, f end + menu[#menu + 1] = function() return { "---", "", "off" }, nil end menu[#menu + 1] = function() - local m = { _("Left operand"), leftop, "" } - menu_lim(leftop, 1, #menu_blocks[1] + 1, m) - if leftop == #menu_blocks[1] + 1 then - m[2] = _("Current") - end - return m, function(event) local r leftop, r = incdec(event, leftop, 1, #menu_blocks[1] + 1) return r end + local m = { _(leftop), "", 0 } + menu_lim(leftop, 1, #menu_blocks[1], m) + m[1] = string.format("Slot %d", leftop) + return m, function(event) local r leftop, r = incdec(event, leftop, 1, #menu_blocks[1]) leftop_text = "Slot " .. leftop return r end end menu[#menu + 1] = function() - local m = { _("Operator"), optable[opsel], "" } + local m = { _(optable[opsel]), "", 0 } menu_lim(opsel, 1, #optable, m) local function f(event) local r opsel, r = incdec(event, opsel, 1, #optable) if event == "left" or event == "right" or event == "comment" then if optable[opsel] == "lt" then - manager:machine():popmessage(_("Left less than right, value is difference")) + manager:machine():popmessage(_("Left less than right")) elseif optable[opsel] == "gt" then - manager:machine():popmessage(_("Left greater than right, value is difference")) + manager:machine():popmessage(_("Left greater than right")) elseif optable[opsel] == "eq" then manager:machine():popmessage(_("Left equal to right")) elseif optable[opsel] == "ne" then - manager:machine():popmessage(_("Left not equal to right, value is difference")) + manager:machine():popmessage(_("Left not equal to right")) elseif optable[opsel] == "beq" then manager:machine():popmessage(_("Left equal to right with bitmask")) elseif optable[opsel] == "bne" then @@ -603,15 +698,21 @@ function cheatfind.startplugin() if optable[opsel]:sub(3, 3) == "v" then return nil end - local m = { _("Right operand"), rightop, "" } + local m = { _(rightop), "", 0 } menu_lim(rightop, 1, #menu_blocks[1], m) - return m, function(event) local r rightop, r = incdec(event, rightop, 1, #menu_blocks[1]) return r end + m[1] = string.format("Slot %d", rightop) + return m, function(event) local r rightop, r = incdec(event, rightop, 1, #menu_blocks[1]) rightop_text = "Slot " .. rightop return r end end menu[#menu + 1] = function() if optable[opsel] == "bne" or optable[opsel] == "beq" or optable[opsel] == "eq" then return nil end - local m = { _("Value"), value, "" } + local m + if optable[opsel] == "ltv" or optable[opsel] == "gtv" or optable[opsel] == "eqv" or optable[opsel] == "nev" then + m = { _("Value"), value, "" } + else + m = { _("Difference"), value, "" } + end local max = 100 -- max value? menu_lim(value, 0, max, m) if value == 0 and optable[opsel]:sub(3, 3) ~= "v" then @@ -625,6 +726,62 @@ function cheatfind.startplugin() menu_lim(width, 1, #formtable, m) return m, function(event) local r width, r = incdec(event, width, 1, #formtable) return r end end + + menu[#menu + 1] = function() + local m = { _("Test/Write Poke Value"), pokevaltable[pokevalsel], 0 } + menu_lim(pokevalsel, 1, #pokevaltable, m) + local function f(event) + local r + pokevalsel, r = incdec(event, pokevalsel, 1, #pokevaltable) + if event == "left" or event == "right" or event == "comment" then + if pokevalsel == 1 then + manager:machine():popmessage(_("Use this if you want to poke the Slot 1 value (eg. You started with something but lost it)")) + elseif pokevalsel == 2 then + manager:machine():popmessage(_("Use this if you want to poke the Last Slot value (eg. You started without an item but finally got it)")) + elseif pokevalsel == 3 then + manager:machine():popmessage(_("Use this if you want to poke 0x00")) + elseif pokevalsel == 4 then + manager:machine():popmessage(_("Use this if you want to poke 0x01")) + elseif pokevalsel == 5 then + manager:machine():popmessage(_("Use this if you want to poke 0x02")) + elseif pokevalsel == 6 then + manager:machine():popmessage(_("Use this if you want to poke 0x03")) + elseif pokevalsel == 7 then + manager:machine():popmessage(_("Use this if you want to poke 0x04")) + elseif pokevalsel == 8 then + manager:machine():popmessage(_("Use this if you want to poke 0x05")) + elseif pokevalsel == 9 then + manager:machine():popmessage(_("Use this if you want to poke 0x06")) + elseif pokevalsel == 10 then + manager:machine():popmessage(_("Use this if you want to poke 0x07")) + elseif pokevalsel == 11 then + manager:machine():popmessage(_("Use this if you want to poke 0x08")) + elseif pokevalsel == 12 then + manager:machine():popmessage(_("Use this if you want to poke 0x09")) + elseif pokevalsel == 13 then + manager:machine():popmessage(_("Use this if you want to poke 0x63 (Decimal 99)")) + elseif pokevalsel == 14 then + manager:machine():popmessage(_("Use this if you want to poke 0x99 (BCD 99)")) + elseif pokevalsel == 15 then + manager:machine():popmessage(_("Use this if you want to poke 0xFF (Decimal 255)")) + elseif pokevalsel == 16 then + manager:machine():popmessage(_("Use this if you want to poke 0x3E7 (Decimal 999)")) + elseif pokevalsel == 17 then + manager:machine():popmessage(_("Use this if you want to poke 0x999 (BCD 999)")) + elseif pokevalsel == 18 then + manager:machine():popmessage(_("Use this if you want to poke 0x270F (Decimal 9999)")) + elseif pokevalsel == 19 then + manager:machine():popmessage(_("Use this if you want to poke 0x9999 (BCD 9999)")) + elseif pokevalsel == 20 then + manager:machine():popmessage(_("Use this if you want to poke 0xFFFF (Decimal 65535)")) + end + end + return r + end + return m, f + end + + menu[#menu + 1] = function() if optable[opsel] == "bne" or optable[opsel] == "beq" then return nil @@ -716,10 +873,66 @@ function cheatfind.startplugin() local function match_exec(match) local dev = devtable[devcur] - local cheat = { desc = string.format(_("Test cheat at addr %08X"), match.addr), script = {} } + local wid = formtable[width]:sub(3, 3) local widchar + local pokevalue local form + + if pokevalsel == 1 then + pokevalue = match.oldval + elseif pokevalsel == 2 then + pokevalue = match.newval + elseif pokevalsel == 3 then + pokevalue = 0 + elseif pokevalsel == 4 then + pokevalue = 1 + elseif pokevalsel == 5 then + pokevalue = 2 + elseif pokevalsel == 6 then + pokevalue = 3 + elseif pokevalsel == 7 then + pokevalue = 4 + elseif pokevalsel == 8 then + pokevalue = 5 + elseif pokevalsel == 9 then + pokevalue = 6 + elseif pokevalsel == 10 then + pokevalue = 7 + elseif pokevalsel == 11 then + pokevalue = 8 + elseif pokevalsel == 12 then + pokevalue = 9 + elseif pokevalsel == 13 then + pokevalue = 99 + elseif pokevalsel == 14 then + pokevalue = 153 + elseif pokevalsel == 15 then + pokevalue = 255 + elseif pokevalsel == 16 and wid == "1" then + pokevalue = 99 + elseif pokevalsel == 17 and wid == "1" then + pokevalue = 153 + elseif pokevalsel == 18 and wid == "1" then + pokevalue = 99 + elseif pokevalsel == 19 and wid == "1" then + pokevalue = 153 + elseif pokevalsel == 20 and wid == "1" then + pokevalue = 255 + elseif pokevalsel == 16 then + pokevalue = 999 + elseif pokevalsel == 17 then + pokevalue = 2457 + elseif pokevalsel == 18 then + pokevalue = 9999 + elseif pokevalsel == 19 then + pokevalue = 39321 + elseif pokevalsel == 20 then + pokevalue = 65535 + end + + local cheat = { desc = string.format(_("Test Cheat %08X:%02X"), match.addr, pokevalue), script = {} } + if wid == "2" then wid = "u16" form = "%08x %04x" @@ -745,17 +958,16 @@ function cheatfind.startplugin() form = "%08x %02x" widchar = "b" end - - + if getmetatable(dev.space).__name:match("device_t") then cheat.ram = { ram = dev.tag } - cheat.script.run = "ram:write(" .. match.addr .. "," .. match.newval .. ")" + cheat.script.run = "ram:write(" .. match.addr .. "," .. pokevalue .. ")" elseif getmetatable(dev.space).__name:match("memory_share") then cheat.share = { share = dev.tag } - cheat.script.run = "share:write_" .. wid .. "(" .. match.addr .. "," .. match.newval .. ")" + cheat.script.run = "share:write_" .. wid .. "(" .. match.addr .. "," .. pokevalue .. ")" else cheat.space = { cpu = { tag = dev.tag, type = dev.sname } } - cheat.script.run = "cpu:write_" .. wid .. "(" .. match.addr .. "," .. match.newval .. ")" + cheat.script.run = "cpu:write_" .. wid .. "(" .. match.addr .. "," .. pokevalue .. ")" end if match.mode == 1 then if not _G.ce then @@ -787,8 +999,9 @@ function cheatfind.startplugin() local json = require("json") cheat.desc = "%s" cheat_save.json = json.stringify({[1] = cheat}, {indent = true}) - cheat_save.xml = string.format("<mamecheat version=\"1\">\n<cheat desc=\"%%s\">\n<script state=\"run\">\n<action>%s.pp%s@%X=%X</action>\n</script>\n</cheat>\n</mamecheat>", dev.tag:sub(2), widchar, match.addr, match.newval) - cheat_save.simple = string.format("%s,%s,%X,%s,%X,%%s\n", setname, dev.tag, match.addr, widchar, match.newval) + cheat_save.xml = string.format("<mamecheat version=\"1\">\n <cheat desc=\"%%s\">\n <script state=\"run\">\n <action>%s.pp%s@%X=%X</action>\n </script>\n </cheat>\n</mamecheat>", dev.tag:sub(2), widchar, match.addr, match.newval) + cheat_save.simple = string.format("%s,%s,%X,%s,%X,%%s\n", setname, dev.tag, match.addr, widchar, pokevalue) + cheat_save.dat = string.format(":%s:40000000:%X:%08X:FFFFFFFF:%%s\n", setname, match.addr, pokevalue) manager:machine():popmessage(string.format(_("Default name is %s"), cheat_save.name)) return true else @@ -813,7 +1026,7 @@ function cheatfind.startplugin() match.mode = 1 end local modes = { _("Test"), _("Write"), _("Watch") } - local m = { string.format("%08x" .. bitwidth .. bitwidth, match.addr, match.oldval, + local m = { string.format("%08x" .. bitwidth .. bitwidth, match.addr, match.oldval, match.newval), modes[match.mode], 0 } menu_lim(match.mode, 1, #modes, m) local function f(event) @@ -855,6 +1068,11 @@ function cheatfind.startplugin() end local function menu_callback(index, event) + if event == "cancel" and pausesel == 1 then + emu.unpause() + menu_is_showing = false + return {0,0,0} + end return menu_func[index](event) end emu.register_menu(menu_callback, menu_populate, _("Cheat Finder")) @@ -863,8 +1081,20 @@ function cheatfind.startplugin() local height = mame_manager:ui():get_line_height() for num, watch in ipairs(watches) do screen:draw_text("left", num * height, string.format(watch.format, watch.addr, watch.func())) - end + end + if tabbed_out and manager:ui():is_menu_active() then + emu.pause() + menu_is_showing = true + tabbed_out = false + end end) + emu.register_periodic(function () + if menu_is_showing and not manager:ui():is_menu_active() then + emu.unpause() + menu_is_showing = false + tabbed_out = true + end + end) end return exports |