summaryrefslogtreecommitdiffstats
path: root/plugins/inputmacro/init.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/init.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/init.lua')
-rw-r--r--plugins/inputmacro/init.lua133
1 files changed, 133 insertions, 0 deletions
diff --git a/plugins/inputmacro/init.lua b/plugins/inputmacro/init.lua
new file mode 100644
index 00000000000..ef88efeadcd
--- /dev/null
+++ b/plugins/inputmacro/init.lua
@@ -0,0 +1,133 @@
+-- license:BSD-3-Clause
+-- copyright-holders:Vas Crabb
+local exports = {
+ name = 'inputmacro',
+ version = '0.0.1',
+ description = 'Input macro plugin',
+ license = 'The BSD 3-Clause License',
+ author = { name = 'Vas Crabb' } }
+
+
+local inputmacro = exports
+
+function inputmacro.startplugin()
+ --[[
+ Configuration data:
+ * name: display name (string)
+ * binding: activation sequence (input sequence)
+ * earlycancel: cancel or complete on release (Boolean)
+ * loop: -1 = release, 0 = prolong, >0 = loop to step on hold (int)
+ * steps:
+ * inputs:
+ * port: port (I/O port)
+ * field: field (I/O port field)
+ * delay: delay before activating inputs in frames (integer)
+ * duration: duration to activate inputs for (integer)
+
+ Live state:
+ * step: current step (integer or nil)
+ * frame: frame of current step, starting at 1 (integer)
+ ]]
+ local macros = { }
+ local active_inputs = { }
+ local shortname
+ local menu
+ local input
+
+ local function activate_inputs(inputs)
+ for index, input in ipairs(inputs) do
+ active_inputs[string.format('%s.%d.%d', input.port.tag, input.field.mask, input.field.type)] = input.field
+ end
+ end
+
+ local function process_frame()
+ previous_inputs = active_inputs
+ active_inputs = { }
+
+ for index, macro in ipairs(macros) do
+ if macro.step then
+ if macro.earlycancel and (not input:seq_pressed(macro.binding)) then
+ -- stop immediately on release if early cancel set
+ macro.step = nil
+ else
+ -- advance frame
+ macro.frame = macro.frame + 1
+ local step = macro.steps[macro.step]
+ if macro.frame > (step.delay + step.duration) then
+ if macro.step < #macro.steps then
+ -- not the last step, advance step
+ macro.step = macro.step + 1
+ macro.frame = 1
+ step = macro.steps[macro.step]
+ elseif not input:seq_pressed(macro.binding) then
+ -- input released and macro completed
+ macro.step = nil
+ step = nil
+ elseif macro.loop > 0 then
+ -- loop to step
+ macro.step = macro.loop
+ macro.frame = 1
+ elseif macro.loop < 0 then
+ -- release if held
+ step = nil
+ end
+ end
+ if step and (macro.frame > step.delay) then
+ activate_inputs(step.inputs)
+ end
+ end
+ elseif input:seq_pressed(macro.binding) then
+ -- initial activation
+ macro.step = 1
+ macro.frame = 1
+ local step = macro.steps[1]
+ if step.delay == 0 then
+ -- no delay on first step, activate inputs
+ activate_inputs(step.inputs)
+ end
+ end
+ end
+
+ for key, field in pairs(active_inputs) do
+ field:set_value(1)
+ end
+ for key, field in pairs(previous_inputs) do
+ if not active_inputs[key] then
+ field:set_value(0)
+ end
+ end
+ end
+
+ local function start()
+ input = manager.machine.input
+ if shortname ~= emu.romname() then
+ local persister = require('inputmacro/inputmacro_persist')
+ macros = persister.load_settings()
+ shortname = emu.romname()
+ end
+ end
+
+ local function stop()
+ local persister = require('inputmacro/inputmacro_persist')
+ persister:save_settings(macros)
+ end
+
+ local function menu_callback(index, event)
+ return menu:handle_event(index, event)
+ end
+
+ local function menu_populate()
+ if not menu then
+ menu = require('inputmacro/inputmacro_menu')
+ menu:init(macros)
+ end
+ return menu:populate()
+ end
+
+ emu.register_frame_done(process_frame)
+ emu.register_start(start)
+ emu.register_stop(stop)
+ emu.register_menu(menu_callback, menu_populate, _('Input Macros'))
+end
+
+return exports