diff options
Diffstat (limited to 'plugins/inputmacro/init.lua')
-rw-r--r-- | plugins/inputmacro/init.lua | 133 |
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 |