mame/plugins/autofire/init.lua
Vas Crabb b67b969bf0 -Improved some Lua APIs:
* Moved several machine lifecycle callbacks to the notifier/subscriber
  model.  The old callback registration model is still available for
  them for now, but prints a deprecation warning.
* Added pre-save/post-load notifications.
* Use a single allocated timer rather than one anonymous timer per
  waiter.  Waiters no longer prevent saved states from being loaded.
* Clean up outstanding waiters on stop or state load rather than just
  leaking them.
* Started documenting parts of the emulator interface object that should
  be relatively stable.

-imagedev/avivideo.cpp: Fixed an object leak on unload.  Also changed
 some other media image devices to use smart pointers.
2023-04-07 06:20:40 +10:00

115 lines
3.1 KiB
Lua

-- license:BSD-3-Clause
-- copyright-holders:Jack Li
local exports = {
name = 'autofire',
version = '0.0.4',
description = 'Autofire plugin',
license = 'BSD-3-Clause',
author = { name = 'Jack Li' } }
local autofire = exports
local frame_subscription, stop_subscription
function autofire.startplugin()
-- List of autofire buttons, each being a table with keys:
-- 'port' - port name of the button being autofired
-- 'mask' - mask of the button field being autofired
-- 'type' - input type of the button being autofired
-- 'key' - input_seq of the keybinding
-- 'key_cfg' - configuration string for the keybinding
-- 'on_frames' - number of frames button is pressed
-- 'off_frames' - number of frames button is released
-- 'button' - reference to ioport_field
-- 'counter' - position in autofire cycle
local buttons = {}
local input_manager
local menu_handler
local function process_frame()
local function process_button(button)
local pressed = input_manager:seq_pressed(button.key)
if pressed then
local state = button.counter < button.on_frames and 1 or 0
button.counter = (button.counter + 1) % (button.on_frames + button.off_frames)
return state
else
button.counter = 0
return 0
end
end
-- Resolves conflicts between multiple autofire keybindings for the same button.
local button_states = {}
for i, button in ipairs(buttons) do
if button.button then
local key = button.port .. '\0' .. button.mask .. '.' .. button.type
local state = button_states[key] or {0, button.button}
state[1] = process_button(button) | state[1]
button_states[key] = state
end
end
for i, state in pairs(button_states) do
if state[1] ~= 0 then
state[2]:set_value(state[1])
else
state[2]:clear_value()
end
end
end
local function load_settings()
local loader = require('autofire/autofire_save')
if loader then
buttons = loader:load_settings()
end
input_manager = manager.machine.input
end
local function save_settings()
local saver = require('autofire/autofire_save')
if saver then
saver:save_settings(buttons)
end
menu_handler = nil
input_manager = nil
buttons = {}
end
local function menu_callback(index, event)
if menu_handler then
return menu_handler:handle_menu_event(index, event, buttons)
else
return false
end
end
local function menu_populate()
if not menu_handler then
local status, msg = pcall(function () menu_handler = require('autofire/autofire_menu') end)
if not status then
emu.print_error(string.format('Error loading autofire menu: %s', msg))
end
if menu_handler then
menu_handler:init_menu(buttons)
end
end
if menu_handler then
return menu_handler:populate_menu(buttons)
else
return {{_p('plugin-autofire', 'Failed to load autofire menu'), '', 'off'}}
end
end
frame_subscription = emu.add_machine_frame_notifier(process_frame)
emu.register_prestart(load_settings)
stop_subscription = emu.add_machine_stop_notifier(save_settings)
emu.register_menu(menu_callback, menu_populate, _p('plugin-autofire', 'Autofire'))
end
return exports