summaryrefslogtreecommitdiffstatshomepage
path: root/plugins/cheatfind/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/cheatfind/init.lua')
-rw-r--r--plugins/cheatfind/init.lua182
1 files changed, 132 insertions, 50 deletions
diff --git a/plugins/cheatfind/init.lua b/plugins/cheatfind/init.lua
index d2c29c7ab53..a777a908e36 100644
--- a/plugins/cheatfind/init.lua
+++ b/plugins/cheatfind/init.lua
@@ -63,6 +63,7 @@ function cheatfind.startplugin()
-- compare two data blocks
function cheat.comp(olddata, newdata, oper, val, signed, width, endian)
local ret = {}
+ local ref = {} -- this is a helper for comparing two match lists
local format = ""
local size = olddata.size
@@ -73,27 +74,27 @@ function cheatfind.startplugin()
end
if width == 16 then
size = size & 0xfffe
- if signed == "signed" then
+ if signed == 1 then
format = format .. "h"
else
format = format .. "H"
end
elseif width == 32 then
size = size & 0xfffc
- if signed == "signed" then
+ if signed == 1 then
format = format .. "l"
else
format = format .. "L"
end
elseif width == 64 then
size = size & 0xfff8
- if signed == "signed" then
+ if signed == 1 then
format = format .. "j"
else
format = format .. "J"
end
else
- if signed == "signed" then
+ if signed == 1 then
format = format .. "b"
else
format = format .. "B"
@@ -115,6 +116,7 @@ function cheatfind.startplugin()
ret[#ret + 1] = { addr = olddata.start + i - 1,
oldval = old,
newval = new}
+ ref[ret[#ret].addr] = #ret
end
end
end
@@ -127,6 +129,7 @@ function cheatfind.startplugin()
ret[#ret + 1] = { addr = olddata.start + i - 1,
oldval = old,
newval = new}
+ ref[ret[#ret].addr] = #ret
end
end
end
@@ -138,11 +141,65 @@ function cheatfind.startplugin()
ret[#ret + 1] = { addr = olddata.start + i - 1,
oldval = old,
newval = new}
+ ref[ret[#ret].addr] = #ret
+ end
+ end
+ elseif oper == "!" or oper == "ne" then
+ for i = 1, size do
+ local old = string.unpack(format, olddata.block, i)
+ local new = string.unpack(format, newdata.block, i)
+ if old ~= new then
+ ret[#ret + 1] = { addr = olddata.start + i - 1,
+ oldval = old,
+ newval = new}
+ ref[ret[#ret].addr] = #ret
+ end
+ end
+ elseif oper == "^" or oper == "xor" then
+ if val >= width then
+ return {}
+ end
+ for i = 1, size do
+ local old = string.unpack(format, olddata.block, i)
+ local new = string.unpack(format, newdata.block, i)
+ if ((old ~ new) & (1 << val)) ~= 0 then
+ ret[#ret + 1] = { addr = olddata.start + i - 1,
+ oldval = old,
+ newval = new}
+ ref[ret[#ret].addr] = #ret
end
end
end
- return ret
+ return ret, ref
+ end
+
+ -- compare successive pairs of blocks from a table returning only addresses that match every comparison
+ function cheat.compall(dattable, oper, val, signed, width, endian)
+ if #dattable < 2 then
+ return {}
+ end
+ local matches, refs = cheat.comp(dattable[1], dattable[2], oper, val, signed, width, endian)
+ local nonmatch = {}
+ for i = 2, #dattable - 1 do
+ local matchnext, refsnext = cheat.comp(dattable[i], dattable[i+1], oper, val, signed, width, endian)
+ for addr, ref in pairs(refs) do
+ if not refsnext[addr] then
+ nonmatch[ref] = true
+ refs[addr] = nil
+ else
+ matches[ref].newval = matchnext[refsnext[addr]].newval
+ end
+ end
+ end
+ local resort = {}
+ for num, match in pairs(matches) do
+ if not nonmatch[num] then
+ resort[#resort + 1] = match
+ end
+ end
+ return resort
end
+
-- compare a data block to the current state
function cheat.compcur(olddata, oper, val, signed, width, endian)
@@ -154,11 +211,13 @@ function cheatfind.startplugin()
local devtable = {}
local devsel = 1
+ local devcur = 1
local bitwidth = 3
local signed = 0
local endian = 0
- local optable = { "<", ">", "=" }
+ local optable = { "<", ">", "=", "!", "^" }
local opsel = 1
+ local bit = 0
local value = 0
local leftop = 1
local rightop = 0
@@ -166,19 +225,20 @@ function cheatfind.startplugin()
local matchsel = 1
local menu_blocks = {}
local midx = { region = 1, init = 2, save = 3, width = 5, signed = 6, endian = 7, op = 8, val = 9,
- lop = 10, rop = 11, comp = 12, match = 14 }
+ lop = 10, rop = 11, comp = 12, match = 14 }
local function start()
devtable = {}
devsel = 1
- devsel = 1
+ devcur = 1
bitwidth = 3
signed = 0
endian = 0
opsel = 1
+ bit = 0
value = 0
leftop = 1
- rightop = 0
+ rightop = 1
matches = {}
matchsel = 1
menu_blocks = {}
@@ -218,14 +278,14 @@ function cheatfind.startplugin()
end
end
- menu[midx.region] = { "CPU or RAM", devtable[devsel].tag, "" }
+ menu[midx.region] = { "CPU or RAM", devtable[devsel].tag, 0 }
if #devtable == 1 then
menu[midx.region][3] = 0
else
menu_lim(devsel, 1, #devtable, menu[midx.region])
end
menu[midx.init] = { "Init", "", 0 }
- if next(menu_blocks) then
+ if #menu_blocks ~= 0 then
menu[midx.save] = { "Save current", "", 0 }
menu[midx.save + 1] = { "---", "", "off" }
menu[midx.width] = { "Bit Width", 1 << bitwidth , 0 }
@@ -242,24 +302,28 @@ function cheatfind.startplugin()
end
menu[midx.op] = { "Operator", optable[opsel], "" }
menu_lim(opsel, 1, #optable, menu[midx.op])
- menu[midx.val] = { "Value", value, "" }
- menu_lim(value, 0, 100, menu[midx.val]) -- max value?
- if value == 0 then
- menu[midx.val][2] = "Any"
+ if optable[opsel] == "^" then
+ menu[midx.val] = { "Bit", bit, "" }
+ menu_lim(bit, 0, (1 << bitwidth), menu[midx.val])
+ else
+ menu[midx.val] = { "Value", value, "" }
+ menu_lim(value, 0, 100, menu[midx.val]) -- max value?
+ if value == 0 then
+ menu[midx.val][2] = "Any"
+ end
end
menu[midx.lop] = { "Left operand", leftop, "" }
- if #menu_blocks == 1 then
- menu[midx.lop][3] = 0
- else
- menu_lim(leftop, 1, #menu_blocks, menu[midx.lop])
+ menu_lim(leftop, 1, #menu_blocks[1] + 1, menu[midx.lop])
+ if leftop == #menu_blocks[1] + 1 then
+ menu[midx.lop][2] = "All"
end
menu[midx.rop] = { "Right operand", rightop, "" }
- menu_lim(rightop, 0, #menu_blocks, menu[midx.rop])
- if rightop == 0 then
+ menu_lim(rightop, 1, #menu_blocks[1] + 1, menu[midx.rop])
+ if rightop == #menu_blocks[1] + 1 then
menu[midx.rop][2] = "Current"
end
menu[midx.comp] = { "Compare", "", 0 }
- if next(matches) then
+ if #matches ~= 0 then
menu[midx.comp + 1] = { "---", "", "off" }
menu[midx.match] = { "Match block", matchsel, "" }
if #matches == 1 then
@@ -304,70 +368,87 @@ function cheatfind.startplugin()
end
if index == midx.region then
- devsel = incdec(devsel, 1, #devtable)
- elseif index == midx.init then
- if event == "select" then
- menu_blocks = {{}}
- matches = {}
- for num, region in ipairs(devtable[devsel].ram) do
- menu_blocks[1][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
- end
- manager:machine():popmessage("Data cleared and current state saved")
- ret = true
+ if (event == "left" or event == "right") and #menu_blocks ~= 0 then
+ manager:machine():popmessage("Changes to this only take effect when Init is selected")
end
+ devsel = incdec(devsel, 1, #devtable)
+ return true
elseif index == midx.init then
if event == "select" then
- menu_blocks = {{}}
+ menu_blocks = {}
matches = {}
- for num, region in ipairs(devtable[devsel].ram) do
- menu_blocks[1][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
+ 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("Data cleared and current state saved")
ret = true
end
+ devcur = devsel
elseif index == midx.save then
if event == "select" then
- menu_blocks[#menu_blocks + 1] = {}
- for num, region in ipairs(devtable[devsel].ram) do
- menu_blocks[#menu_blocks][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
+ 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")
ret = true
end
elseif index == midx.width then
bitwidth = incdec(bitwidth, 3, 6)
+ if event == "left" or event == "right" then
+ bit = 0
+ end
elseif index == midx.signed then
signed = incdec(signed, 0, 1)
elseif index == midx.endian then
endian = incdec(endian, 0, 1)
elseif index == midx.op then
- if event == "up" or event == "down" or event == "comment" then
+ if event == "left" or event == "right" or event == "comment" then
if optable[opsel] == "<" then
manager:machine():popmessage("Left less than right, value is difference")
elseif optable[opsel] == ">" then
manager:machine():popmessage("Left greater than right, value is difference")
elseif optable[opsel] == "=" then
manager:machine():popmessage("Left equal to right, value is ignored")
+ elseif optable[opsel] == "!" then
+ manager:machine():popmessage("Left not equal to right, value is ignored")
+ elseif optable[opsel] == "^" then
+ manager:machine():popmessage("Left bit different than right")
end
- else
- opsel = incdec(opsel, 1, #optable)
end
+ opsel = incdec(opsel, 1, #optable)
elseif index == midx.val then
- value = incdec(value, 0, 100)
+ if optable[opsel] == "^" then
+ bit = incdec(bit, 0, (1 << bitwidth))
+ else
+ value = incdec(value, 0, 100)
+ end
elseif index == midx.lop then
- leftop = incdec(leftop, 1, #menu_blocks)
+ leftop = incdec(leftop, 1, #menu_blocks[1] + 1)
+ if (event == "left" or event == "right" or event == "comment") and leftop == #menu_blocks[1] + 1 then
+ manager:machine():popmessage("Any compares every saved data pair and returns only matches that are true for all. Right operand is ignored.")
+ end
elseif index == midx.rop then
- rightop = incdec(rightop, 0, #menu_blocks)
+ rightop = incdec(rightop, 1, #menu_blocks[1] + 1)
elseif index == midx.comp then
if event == "select" then
matches = {}
- for num = 1, #menu_blocks[1] do
- if rightop == 0 then
- matches[#matches + 1] = cheat.compcur(menu_blocks[leftop][num], optable[opsel], value,
- signed, 1 << bitwidth, endian)
+ local val
+ if optable[opsel] == "^" then
+ val = bit
+ else
+ val = value
+ end
+ for num = 1, #menu_blocks do
+ if leftop == #menu_blocks[1] + 1 then
+ matches[#matches + 1] = cheat.compall(menu_blocks[num], optable[opsel], val, signed,
+ 1 << bitwidth, endian)
+ elseif rightop == #menu_blocks[1] + 1 then
+ matches[#matches + 1] = cheat.compcur(menu_blocks[num][leftop], optable[opsel], val,
+ signed, 1 << bitwidth, endian)
else
- matches[#matches + 1] = cheat.comp(menu_blocks[leftop][num], menu_blocks[rightop][num],
- optable[opsel], value, signed, 1 << bitwidth, endian)
+ matches[#matches + 1] = cheat.comp(menu_blocks[num][leftop], menu_blocks[num][rightop],
+ optable[opsel], val, signed, 1 << bitwidth, endian)
end
end
ret = true
@@ -379,6 +460,7 @@ function cheatfind.startplugin()
-- write out a script?
end
end
+ devsel = devcur
return ret
end
emu.register_menu(menu_callback, menu_populate, "Cheat Finder")