summaryrefslogtreecommitdiffstatshomepage
path: root/plugins/inputmacro/inputmacro_persist.lua
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-10-21 04:11:43 +1100
committer Vas Crabb <vas@vastheman.com>2021-10-21 04:11:43 +1100
commitb1c764415931c9700552cd456bfeb20fe41ba622 (patch)
tree83484512a26252374612f51d1683ced38b5e5770 /plugins/inputmacro/inputmacro_persist.lua
parentd42a9fd87e737c0526d35624163f110b290c6d79 (diff)
-plugins: Added an input macro plugin.
-plugins: Sort input selection menus for autofire plugin. -frontend: Fixed another case where the menus may not automatically scroll the first item into view.
Diffstat (limited to 'plugins/inputmacro/inputmacro_persist.lua')
-rw-r--r--plugins/inputmacro/inputmacro_persist.lua145
1 files changed, 145 insertions, 0 deletions
diff --git a/plugins/inputmacro/inputmacro_persist.lua b/plugins/inputmacro/inputmacro_persist.lua
new file mode 100644
index 00000000000..04d310faeef
--- /dev/null
+++ b/plugins/inputmacro/inputmacro_persist.lua
@@ -0,0 +1,145 @@
+-- Helpers
+
+local function settings_path()
+ return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/inputmacro/'
+end
+
+local function settings_filename()
+ return emu.romname() .. '.cfg'
+end
+
+local function make_macro(setting)
+ if (setting.name == nil) or (setting.binding == nil) or (setting.earlycancel == nil) or (setting.loop == nil) or (setting.steps == nil) then
+ return nil
+ end
+
+ local result = {
+ name = setting.name,
+ binding = manager.machine.input:seq_from_tokens(setting.binding),
+ earlycancel = setting.earlycancel,
+ loop = setting.loop,
+ steps = { } }
+
+ local ioport = manager.machine.ioport
+ for i, step in ipairs(setting.steps) do
+ if step.inputs and step.delay and step.duration then
+ local s = {
+ inputs = { },
+ delay = step.delay,
+ duration = step.duration }
+ for j, input in ipairs(step.inputs) do
+ if input.port and input.mask and input.type then
+ local port = ioport.ports[input.port]
+ if port then
+ local field = port:field(input.mask)
+ if field and (field.type == ioport:token_to_input_type(input.type)) then
+ table.insert(s.inputs, { port = port, field = field })
+ end
+ end
+ end
+ end
+ if #s.inputs > 0 then
+ table.insert(result.steps, s)
+ end
+ end
+ end
+
+ if result.loop > #result.steps then
+ result.loop = -1
+ end
+
+ if #result.steps > 0 then
+ return result
+ else
+ return nil
+ end
+end
+
+local function make_settings(macros)
+ local input = manager.machine.input
+ local ioport = manager.machine.ioport
+ local result = { }
+ for i, macro in ipairs(macros) do
+ local m = {
+ name = macro.name,
+ binding = input:seq_to_tokens(macro.binding),
+ earlycancel = macro.earlycancel,
+ loop = macro.loop,
+ steps = { } }
+ table.insert(result, m)
+ for j, step in ipairs(macro.steps) do
+ local s = {
+ inputs = { },
+ delay = step.delay,
+ duration = step.duration }
+ table.insert(m.steps, s)
+ for k, input in ipairs(step.inputs) do
+ local b = {
+ port = input.port.tag,
+ mask = input.field.mask,
+ type = ioport:input_type_to_token(input.field.type) }
+ table.insert(s.inputs, b)
+ end
+ end
+ end
+ return result
+end
+
+
+-- Entry points
+
+local lib = { }
+
+function lib:load_settings()
+ filename = settings_path() .. settings_filename()
+ local file = io.open(filename, 'r')
+ if not file then
+ return { }
+ end
+ local json = require('json')
+ local settings = json.parse(file:read('a'))
+ file:close()
+ if not settings then
+ emu.print_error(string.format('Error loading input macros: error parsing file "%s" as JSON\n', filename))
+ return { }
+ end
+
+ result = { }
+ for index, setting in ipairs(settings) do
+ local macro = make_macro(setting)
+ if macro then
+ table.insert(result, macro)
+ end
+ end
+ return result
+end
+
+function lib:save_settings(macros)
+ local path = settings_path()
+ local stat = lfs.attributes(path)
+ if not stat then
+ lfs.mkdir(path)
+ elseif stat.mode ~= 'directory' then
+ emu.print_error(string.format('Error saving input macros: "%s" is not a directory\n', path))
+ return
+ end
+ filename = path .. settings_filename()
+
+ if #macros == 0 then
+ os.remove(filename)
+ return
+ end
+
+ local json = require('json')
+ local settings = make_settings(macros)
+ local text = json.stringify(settings, { indent = true })
+ local file = io.open(filename, 'w')
+ if not file then
+ emu.print_error(string.format('Error saving input macros: error opening file "%s" for writing\n', filename))
+ return
+ end
+ file:write(text)
+ file:close()
+end
+
+return lib