diff options
author | 2017-06-15 15:04:04 -0500 | |
---|---|---|
committer | 2017-06-15 15:04:04 -0500 | |
commit | 74894fa5d2c66f06ed0654ee71819c1ee5d13b2f (patch) | |
tree | d3faebcec1eb571a55a81da368ffdfa35d6b0cec /plugins/cheat | |
parent | 18c4a3735df9a92be0368487f70c4b34022ea3b0 (diff) |
plugins/cheat: refactor and add more ar support (nw)
Diffstat (limited to 'plugins/cheat')
-rw-r--r-- | plugins/cheat/cheat_simple.lua | 221 |
1 files changed, 127 insertions, 94 deletions
diff --git a/plugins/cheat/cheat_simple.lua b/plugins/cheat/cheat_simple.lua index 998e4a7fcd1..7058dfa8a0b 100644 --- a/plugins/cheat/cheat_simple.lua +++ b/plugins/cheat/cheat_simple.lua @@ -1,13 +1,13 @@ -- converter for simple cheats --- simple cheats are single address every frame ram or gg,ar cheats in one file called cheat.simple +-- simple cheats are single address every frame ram, rom or gg,ar cheats in one file called cheat.simple -- --- ram cheat format: <set name>,<cputag>,<hex offset>,<b|w|d|q - size>,<hex value>,<desc> +-- ram/rom cheat format: <set name>,<cputag|regiontag>,<hex offset>,<b|w|d|q - size>,<hex value>,<desc> -- only program address space is supported, comments are prepended with ; -- size is b - u8, w - u16, d - u32, q - u64 -- -- gg,ar cheat format: <set name>,<gg|ar - type>,<code>,<desc> like "nes/smb,gg,SXIOPO,Infinite Lives" -- gg for game genie -- nes, snes, megadriv, gamegear, gameboy --- ar for action replay -- nes +-- ar for action replay -- nes, snes, megadriv, gamegear, sms -- -- set name is <softlist>/<entry> like "nes/smb" for softlist items -- Don't use commas in the description @@ -23,10 +23,43 @@ end local codefuncs = {} +local function prepare_rom_cheat(desc, region, addr, val, size, banksize, comp) + local cheat = { desc = desc, region = { rom = region } } + cheat.script = { off = "if on then rom:write_u8(addr, save) end" } + if banksize and comp then + local rom = manager:machine():memory().regions[region] + local bankaddr = addr & (banksize - 1) + addr = nil + if not rom then + error("rom cheat invalid region " .. desc) + end + for i = 0, rom.size, banksize do + if rom:read_u8(i + bankaddr) == comp then + addr = i + bankaddr + break + end + end + if not addr then + error("rom cheat compare value not found " .. desc) + end + end + cheat.script.on = string.format([[ + on = true + addr = %d + save = rom:read_u%d(addr) + rom:write_u8(addr, %d)]], addr, size, val) + return cheat +end + +local function prepare_ram_cheat(desc, tag, addr, val, size) + local cheat = { desc = desc, space = { cpup = { tag = tag, type = "program" } } } + cheat.script = { run = "cpup:write_u" .. size .. "(" .. addr .. "," .. val .. ", true)" } + return cheat +end + function codefuncs.nes_gg(desc, code) local xlate = { A = 0, P = 1, Z = 2, L = 3, G = 4, I = 5, T = 6, Y = 7, E = 8, O = 9, X = 10, U = 11, K = 12, S = 13, V = 14, N = 15 } - local cheat = { desc = desc, region = { rom = ":nes_slot:cart:prg_rom" } } local value = 0 code:upper():gsub("(.)", function(s) if not xlate[s] then @@ -35,39 +68,22 @@ function codefuncs.nes_gg(desc, code) value = (value << 4) | xlate[s] end) local addr, newval, comp - cheat.script = { off = "if on then rom:write_u8(addr, save) end" } if #code == 6 then addr = ((value >> 4) & 7) | ((value >> 8) & 0x78) | ((value >> 12) & 0x80) | ((value << 8) & 0x700) | ((value << 4) & 0x7800) newval = ((value >> 20) & 7) | (value & 8) | ((value >> 12) & 0x70) | ((value >> 16) & 0x80) - cheat.script.on = string.format([[ - on = true - addr = %d - save = rom:read_u8(addr) - rom:write_u8(addr, %d)]], addr, newval) + return prepare_rom_cheat(desc, ":nes_slot:cart:prg_rom", addr, newval, 8) elseif #code == 8 then addr = ((value >> 12) & 7) | ((value >> 16) & 0x78) | ((value >> 20) & 0x80) | (value & 0x700) | ((value >> 4) & 0x7800) newval = ((value >> 28) & 7) | (value & 8) | ((value >> 20) & 0x70) | ((value >> 24) & 0x80) comp = ((value >> 4) & 7) | ((value >> 8) & 8) | ((value << 4) & 0x70) | ((value << 1) & 0x80) -- assume 8K banks, 32K also common but is an easy multiple of 8K - cheat.script.on = string.format([[ - addr = %d - save = %d - for i = 0, rom.size, 8192 do - if rom:read_u8(i + addr) == save then - on = true - addr = i + addr - rom:write_u8(addr, %d) - break - end - end]], addr & 0x3fff, comp, newval) + return prepare_rom_cheat(desc, ":nes_slot:cart:prg_rom", addr, newval, 8, 8192, comp) else error("error game genie cheat incorrect length " .. desc) end - return cheat end function codefuncs.nes_ar(desc, code) - local cheat = { desc = desc, space = { cpup = { tag = ":maincpu", type = "program" } } } code = code:gsub("[: %-]", "") if #code ~= 8 then error("error action replay cheat incorrect length " .. desc) @@ -77,8 +93,39 @@ function codefuncs.nes_ar(desc, code) if not newval or not addr then error("error parsing action replay cheat " .. desc) end - cheat.script = { run = "cpup:write_u8(" .. addr .. "," .. newval .. ", true)" } - return cheat + return prepare_ram_cheat(desc, ":maincpu", addr, newval, 8) +end + +local function snes_prepare_cheat(desc, addr, val) + local bank = addr >> 16 + local offset = addr & 0xffff + if ((bank <= 0x3f) and (offset < 0x2000)) or ((bank & 0xfe) == 0x7e) then + return prepare_ram_cheat(desc, ":maincpu", addr, val, 8) + end + if (manager:machine().devices[":maincpu"].spaces["program"]:read_u8(0xffd5) & 1) == 1 then --hirom + if (bank & 0x7f) <= 0x3f and offset >= 0x8000 then + -- direct map + elseif (bank & 0x7f) >= 0x40 and (bank & 0x7f) <= 0x7d then + addr = addr & 0x3fffff + elseif bank >= 0xfe then + addr = addr & 0x3fffff + else + error("error cheat not rom or ram addr " .. desc) + end + else --lorom + if (bank & 0x7f) <= 0x3f and offset >= 0x8000 then + addr = ((addr >> 1) & 0x3f8000) | (addr & 0x7fff) + elseif (bank & 0x7f) >= 0x40 and (bank & 0x7f) <= 0x6f then + addr = ((addr >> 1) & 0x3f8000) | (addr & 0x7fff) + elseif (bank & 0x7f) >= 0x70 and (bank & 0x7f) <= 0x7d and offset >= 0x8000 then + addr = ((addr >> 1) & 0x3f8000) | (addr & 0x7fff) + elseif bank >= 0xfe and offset >= 0x8000 then + addr = ((addr >> 1) & 0x3f8000) | (addr & 0x7fff) + else + error("error cheat not rom or ram addr " .. desc) + end + end + return prepare_rom_cheat(desc, ":snsslot:cart:rom", addr, val, 8) end function codefuncs.snes_gg(desc, code) @@ -86,8 +133,6 @@ function codefuncs.snes_gg(desc, code) ["6"] = 8, B = 9, C = 10, ["8"] = 11, A = 12, ["2"] = 13, ["3"] = 14, E = 15 } local value = 0 local count = 0 - local cheat = { desc = desc, region = { rom = ":snsslot:cart:rom" } } - cheat.script = { off = "if on then rom:write_u8(addr, save) end" } code:upper():gsub("(.)", function(s) if s == "-" then return @@ -103,40 +148,20 @@ function codefuncs.snes_gg(desc, code) local newval = (value >> 24) & 0xff local addr = ((value >> 6) & 0xf) | ((value >> 12) & 0xf0) | ((value >> 6) & 0x300) | ((value << 10) & 0xc00) | ((value >> 8) & 0xf000) | ((value << 14) & 0xf0000) | ((value << 10) & 0xf00000) - if (manager:machine().devices[":maincpu"].spaces["program"]:read_u8(0xffd5) & 1) == 1 then --hirom - local bank = addr >> 16 - local offset = addr & 0xffff - if (bank & 0x7f) <= 0x3f and offset >= 0x8000 then - -- direct map - elseif (bank & 0x7f) >= 0x40 and (bank & 0x7f) <= 0x7d then - addr = addr & 0x3fffff - elseif bank >= 0xfe then - addr = addr & 0x3fffff - else - error("error game genie cheat not rom addr " .. desc) - end - else --lorom - local bank = addr >> 16 - local offset = addr & 0xffff - if (bank & 0x7f) <= 0x3f and offset >= 0x8000 then - addr = ((addr >> 1) & 0x78000) | (addr & 0x7fff) - elseif (bank & 0x7f) >= 0x40 and (bank & 0x7f) <= 0x6f then - addr = ((addr >> 1) & 0x78000) | (addr & 0x7fff) - elseif (bank & 0x7f) >= 0x70 and (bank & 0x7f) <= 0x7d and offset >= 0x8000 then - addr = ((addr >> 1) & 0x78000) | (addr & 0x7fff) - elseif bank >= 0xfe and offset >= 0x8000 then - addr = ((addr >> 1) & 0x78000) | (addr & 0x7fff) - else - error("error game genie cheat not rom addr " .. desc) - end + return snes_prepare_cheat(desc, addr, newval) +end + +function codefuncs.snes_ar(desc, code) + code = code:gsub("[: %-]", "") + if #code ~= 8 then + error("error action replay cheat incorrect length " .. desc) end - cheat.script.on = string.format([[ - addr = %d - save = rom:read_u8(addr) - on = true - rom:write_u8(addr, %d) - ]], addr, newval) - return cheat + local addr = tonumber(code:sub(1, 6), 16) + local val = tonumber(code:sub(7, 8), 16) + if not addr or not val then + error("error parsing action replay cheat " .. desc) + end + return snes_prepare_cheat(desc, addr, val) end function codefuncs.megadriv_gg(desc, code) @@ -145,8 +170,6 @@ function codefuncs.megadriv_gg(desc, code) ["2"] = 24, ["3"] = 25, ["4"] = 26, ["5"] = 27, ["6"] = 28, ["7"] = 29, ["8"] = 30, ["9"] = 31 } local value = 0 local count = 0 - local cheat = { desc = desc, region = { rom = ":mdslot:cart:rom" } } - cheat.script = { off = "if on then rom:write_u16(addr, save) end" } code:upper():gsub("(.)", function(s) if s == "-" then return @@ -161,18 +184,23 @@ function codefuncs.megadriv_gg(desc, code) end local newval = ((value >> 32) & 0xff) | ((value >> 3) & 0x1f00) | ((value << 5) & 0xe000) local addr = (value & 0xff00ff) | ((value >> 16) & 0xff00) - cheat.script.on = string.format([[ - addr = %d - save = rom:read_u16(addr) - on = true - rom:write_u16(addr, %d) - ]], addr, newval) - return cheat + return prepare_rom_cheat(desc, ":mdslot:cart:rom", addr, newval, 16) +end + +function codefuncs.megadriv_ar(desc, code) + code = code:gsub("[: %-]", "") + if #code ~= 10 then + error("error action replay cheat incorrect length " .. desc) + end + local addr = tonumber(code:sub(1, 7), 16) + local val = tonumber(code:sub(7, 10), 16) + if addr < 0xff0000 then + error("error action replay cheat not ram addr " .. desc) + end + return prepare_ram_cheat(desc, ":maincpu", addr, val, 16) end local function gbgg_ggcodes(desc, code, region) - local cheat = { desc = desc, region = { rom = region } } - cheat.script = { off = "if on then rom:write_u16(addr, save) end" } code = code:gsub("%-", "") local comp if #code == 6 then @@ -193,25 +221,10 @@ local function gbgg_ggcodes(desc, code, region) error("error game genie cheat bad addr " .. desc) end if comp == -1 then - cheat.script.on = string.format([[ - addr = %d - save = rom:read_u8(addr) - on = true - rom:write_u8(addr, %d) - ]], addr, newval) + return prepare_rom_cheat(desc, region, addr, newval, 8) else -- assume 8K banks - cheat.script.on = string.format([[ - addr = %d - save = %d - for i = 0, rom.size, 8192 do - if rom:read_u8(i + addr) == save then - on = true - addr = i + addr - rom:write_u8(addr, %d) - break - end - end]], addr & 0x3fff, comp, newval) + return prepare_rom_cheat(desc, region, addr, newval, 8, 8192, comp) end return cheat end @@ -224,6 +237,21 @@ function codefuncs.gamegear_gg(desc, code) return gbgg_ggcodes(desc, code, ":slot:cart:rom") end +function codefuncs.gamegear_ar(desc, code) + code = code:gsub("[: %-]", "") + if #code ~= 8 then + error("error action replay cheat incorrect length " .. desc) + end + local addr = tonumber(code:sub(1, 6), 16) + local val = tonumber(code:sub(7, 8), 16) + if addr < 0xc000 or addr >= 0xe000 then + error("error action replay cheat not ram addr " .. desc) + end + return prepare_ram_cheat(desc, ":maincpu", addr, val, 8) +end + +codefuncs.sms_ar = codefuncs.gamegear_ar + function simple.conv_cheat(data) local cheats = {} for line in data:gmatch('([^\n;]+)') do @@ -242,17 +270,22 @@ function simple.conv_cheat(data) end end elseif size and val then - cheat = { desc = desc, space = { cpup = { tag = cputag, type = "program" } } } if size == "w" then - size = "u16" + size = 16 elseif size == "d" then - size = "u32" + size = 32 elseif size == "q" then - size = "u64" + size = 64 + else + size = 8 + end + addr = tonumber(addr, 16) + val = tonumber(val, 16) + if manager:machine().devices[cputag] then + cheat = prepare_ram_cheat(desc, cputag, addr, val, size) else - size = "u8" + cheat = prepare_rom_cheat(desc, cputag, addr, val, size) end - cheat.script = { run = "cpup:write_" .. size .. "(0x" .. offset .. ",0x" .. val .. ", true)" } end if cheat then cheats[#cheats + 1] = cheat |