2016-04-07 00:03:11 +02:00
|
|
|
local xml = {}
|
|
|
|
|
|
|
|
-- basic xml parser for mamecheat only
|
|
|
|
local function xml_parse(data)
|
|
|
|
local cheat_str = data:match("<mamecheat.->(.*)</ *mamecheat>")
|
|
|
|
|
|
|
|
local function get_tags(str)
|
|
|
|
local arr = {}
|
|
|
|
while str ~= "" do
|
|
|
|
local tag, attr, stop
|
|
|
|
tag, attr, stop, str = str:match("<([%w!-]+) ?(.-)(/?)[ -]->(.*)")
|
|
|
|
|
|
|
|
if not tag then
|
|
|
|
return arr
|
|
|
|
end
|
|
|
|
if tag:sub(0, 3) ~= "!--" then
|
|
|
|
local block = {}
|
|
|
|
if stop ~= "/" then
|
|
|
|
local nest
|
|
|
|
nest, str = str:match("(.-)</ *" .. tag .. " *>(.*)")
|
|
|
|
local children = get_tags(nest)
|
|
|
|
if not next(children) then
|
|
|
|
nest = nest:gsub("<!--.--->", "")
|
|
|
|
nest = nest:gsub("^%s*(.-)%s*$", "%1")
|
|
|
|
block["text"] = nest
|
|
|
|
else
|
|
|
|
block = children
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if attr then
|
|
|
|
for name, value in attr:gmatch("(%w-)=\"(.-)\"") do
|
|
|
|
block[name] = value:gsub("^%s*(.-)%s*$", "%1")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if not arr[tag] then
|
|
|
|
arr[tag] = {}
|
|
|
|
end
|
|
|
|
arr[tag][#arr[tag] + 1] = block
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return arr
|
|
|
|
end
|
|
|
|
local xml_table = get_tags(cheat_str)
|
|
|
|
return xml_table
|
|
|
|
end
|
|
|
|
|
|
|
|
function xml.conv_cheat(data)
|
|
|
|
local spaces, regions, output
|
|
|
|
data = xml_parse(data)
|
|
|
|
local function convert_expr(data)
|
|
|
|
local write = false
|
|
|
|
|
|
|
|
local function convert_memref(cpu, space, width, addr, rw)
|
|
|
|
local direct = ""
|
2016-04-07 17:37:44 +02:00
|
|
|
local count
|
2016-04-07 00:03:11 +02:00
|
|
|
if space == "p" then
|
|
|
|
fullspace = "program"
|
|
|
|
elseif space == "d" then
|
|
|
|
fullspace = "data"
|
|
|
|
elseif space == "i" then
|
|
|
|
fullspace = "io"
|
|
|
|
elseif space == "r" or space == "o" then
|
|
|
|
fullspace = "program"
|
|
|
|
direct = "direct_"
|
|
|
|
space = "p"
|
|
|
|
end
|
|
|
|
if width == "b" then
|
|
|
|
width = "u8"
|
|
|
|
elseif width == "w" then
|
|
|
|
width = "u16"
|
|
|
|
elseif width == "d" then
|
|
|
|
width = "u32"
|
|
|
|
elseif width == "q" then
|
|
|
|
width = "u64"
|
|
|
|
end
|
|
|
|
local cpuname = cpu:gsub(":", "_")
|
|
|
|
if space == "m" then
|
|
|
|
regions[cpuname .. space] = ":" .. cpu
|
|
|
|
else
|
|
|
|
spaces[cpuname .. space] = { tag = ":" .. cpu, type = fullspace }
|
|
|
|
end
|
|
|
|
if rw == "=" then
|
|
|
|
write = true
|
|
|
|
ret = cpuname .. space .. ":" .. "write_" .. direct .. width .. "(" .. addr .. ","
|
|
|
|
else
|
|
|
|
ret = cpuname .. space .. ":" .. "read_" .. direct .. width .. "(" .. addr .. ")"
|
|
|
|
end
|
|
|
|
if rw == "==" then
|
|
|
|
ret = ret .. "=="
|
|
|
|
end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
local function frame()
|
|
|
|
output = true
|
|
|
|
return "screen:frame_number()"
|
|
|
|
end
|
|
|
|
|
|
|
|
data = data:lower()
|
2016-04-07 17:37:44 +02:00
|
|
|
data = data:gsub("^[(](.-)[)]$", "%1")
|
2016-04-07 00:03:11 +02:00
|
|
|
data = data:gsub("lt", "<")
|
|
|
|
data = data:gsub("ge", ">=")
|
|
|
|
data = data:gsub("gt", ">")
|
|
|
|
data = data:gsub("le", "<=")
|
|
|
|
data = data:gsub("!=", "~=")
|
|
|
|
data = data:gsub("frame", frame)
|
|
|
|
data = data:gsub("band", "&")
|
|
|
|
data = data:gsub("bor", "|")
|
2016-04-07 17:37:44 +02:00
|
|
|
data = data:gsub("rshift", ">>")
|
|
|
|
data = data:gsub("lshift", "<<")
|
2016-04-07 00:03:11 +02:00
|
|
|
data = data:gsub("%f[%w](%x+)%f[%W]", "0x%1")
|
2016-04-07 17:37:44 +02:00
|
|
|
data = data:gsub("([%w_:]-).([pmrodi3])([bwdq])@(%w+) *(=*)", convert_memref)
|
|
|
|
repeat
|
|
|
|
data, count = data:gsub("([%w_:]-).([pmrodi3])([bwdq])@(%b()) *(=*)", convert_memref)
|
|
|
|
until count == 0
|
2016-04-07 00:03:11 +02:00
|
|
|
if write then
|
|
|
|
data = data .. ")"
|
|
|
|
end
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
|
|
|
|
local function convert_output(data)
|
|
|
|
local str = "draw_text(screen,"
|
|
|
|
if data["align"] then
|
|
|
|
str = str .. data["align"]
|
|
|
|
else
|
|
|
|
str = str .. "\"left\""
|
|
|
|
end
|
|
|
|
if data["line"] then
|
|
|
|
str = str .. ",\"" .. data["line"] .. "\""
|
|
|
|
else
|
|
|
|
str = str .. ", \"auto\""
|
|
|
|
end
|
|
|
|
str = str .. ", nil,\"" .. data["format"] .. "\""
|
|
|
|
for count, block in pairs(data["argument"]) do
|
|
|
|
local expr = convert_expr(block["text"])
|
|
|
|
if block["count"] then
|
|
|
|
for i = 0, block["count"] - 1 do
|
|
|
|
str = str .. "," .. expr:gsub("argindex", i)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
str = str .. "," .. expr
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return str .. ")"
|
|
|
|
end
|
|
|
|
|
|
|
|
local function convert_script(data)
|
|
|
|
local str = ""
|
|
|
|
local state = "run"
|
|
|
|
for tag, block in pairs(data) do
|
|
|
|
if tag == "state" then
|
|
|
|
state = block
|
|
|
|
elseif tag == "action" then
|
|
|
|
for count, action in pairs(block) do
|
|
|
|
if action["condition"] then
|
2016-04-07 17:37:44 +02:00
|
|
|
str = str .. " if (" .. convert_expr(action["condition"]) .. ") then "
|
2016-04-07 00:03:11 +02:00
|
|
|
for expr in action["text"]:gmatch("([^,]+)") do
|
|
|
|
str = str .. convert_expr(expr) .. " "
|
|
|
|
end
|
|
|
|
str = str .. "end"
|
|
|
|
else
|
|
|
|
for expr in action["text"]:gmatch("([^,]+)") do
|
|
|
|
str = str .. " " .. convert_expr(expr) .. " "
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif tag == "output" then
|
|
|
|
output = true
|
|
|
|
for count, output in pairs(block) do
|
|
|
|
if output["condition"] then
|
|
|
|
str = str .. " if " .. convert_expr(output["condition"]) .. " then "
|
|
|
|
str = str .. convert_output(output) .. " end "
|
|
|
|
else
|
|
|
|
str = str .. " " .. convert_output(output) .. " "
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return state, str
|
|
|
|
end
|
|
|
|
|
|
|
|
for count, cheat in pairs(data["cheat"]) do
|
|
|
|
spaces = {}
|
|
|
|
regions = {}
|
|
|
|
output = false
|
|
|
|
for tag, block in pairs(cheat) do
|
|
|
|
if tag == "comment" then
|
|
|
|
data["cheat"][count]["comment"] = block[1]["text"]
|
|
|
|
elseif tag == "script" then
|
|
|
|
local scripts = {}
|
|
|
|
for count2, script in pairs(block) do
|
|
|
|
local state, str = convert_script(script)
|
|
|
|
scripts[state] = str
|
|
|
|
end
|
|
|
|
data["cheat"][count]["script"] = scripts
|
|
|
|
elseif tag == "parameter" then
|
2016-04-07 17:37:44 +02:00
|
|
|
if block[1]["min"] then
|
|
|
|
block[1]["min"] = block[1]["min"]:gsub("%$","0x")
|
|
|
|
end
|
|
|
|
if block[1]["max"] then
|
|
|
|
block[1]["max"] = block[1]["max"]:gsub("%$","0x")
|
|
|
|
end
|
|
|
|
if block[1]["step"] then
|
|
|
|
block[1]["step"] = block[1]["step"]:gsub("%$","0x")
|
|
|
|
end
|
|
|
|
data["cheat"][count]["parameter"] = block[1]
|
2016-04-07 00:03:11 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
if next(spaces) then
|
|
|
|
data["cheat"][count]["space"] = {}
|
|
|
|
for name, space in pairs(spaces) do
|
|
|
|
data["cheat"][count]["space"] = {}
|
|
|
|
data["cheat"][count]["space"][name] = { type = space["type"], tag = space["tag"] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if next(regions) then
|
|
|
|
data["cheat"][count]["region"] = {}
|
|
|
|
for name, region in pairs(regions) do
|
|
|
|
data["cheat"][count]["region"] = {}
|
|
|
|
data["cheat"][count]["region"][name] = region
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if output then
|
|
|
|
data["cheat"][count]["screen"] = {}
|
|
|
|
data["cheat"][count]["screen"]["screen"] = ":screen"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return data["cheat"]
|
|
|
|
end
|
|
|
|
|
|
|
|
return xml
|