mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00

Trying to collect messages from everything at once hits some limit in xgettext and causes messages to be lost no, so I've split it up by the second-level source directories. For some reason xgettext thinks overloaded Lua functions are blasphemy, so that has to be worked around, too.
314 lines
8.8 KiB
Lua
314 lines
8.8 KiB
Lua
local lib = {}
|
|
|
|
-- Set of all menus
|
|
local MENU_TYPES = { MAIN = 0, EDIT = 1, ADD = 2, BUTTON = 3 }
|
|
|
|
-- Set of sections within a menu
|
|
local MENU_SECTIONS = { HEADER = 0, CONTENT = 1, FOOTER = 2 }
|
|
|
|
-- Last index of header items (above main content) in menu
|
|
local header_height = 0
|
|
|
|
-- Last index of content items (below header, above footer) in menu
|
|
local content_height = 0
|
|
|
|
-- Stack of menus (see MENU_TYPES)
|
|
local menu_stack = { MENU_TYPES.MAIN }
|
|
|
|
-- Button being created/edited
|
|
local current_button = {}
|
|
|
|
-- Inputs that can be autofired (to list in BUTTON menu)
|
|
local inputs = {}
|
|
|
|
-- Returns the section (from MENU_SECTIONS) and the index within that section
|
|
local function menu_section(index)
|
|
if index <= header_height then
|
|
return MENU_SECTIONS.HEADER, index
|
|
elseif index <= content_height then
|
|
return MENU_SECTIONS.CONTENT, index - header_height
|
|
else
|
|
return MENU_SECTIONS.FOOTER, index - content_height
|
|
end
|
|
end
|
|
|
|
local function create_new_button()
|
|
return {
|
|
on_frames = 1,
|
|
off_frames = 1,
|
|
counter = 0
|
|
}
|
|
end
|
|
|
|
local function is_button_complete(button)
|
|
return button.port and button.field and button.key and button.on_frames and button.off_frames and button.button and button.counter
|
|
end
|
|
|
|
local function is_supported_input(ioport_field)
|
|
-- IPT_BUTTON1 through IPT_BUTTON16 in ioport_type enum (ioport.h)
|
|
return ioport_field.type >= 64 and ioport_field.type <= 79
|
|
end
|
|
|
|
-- Main menu
|
|
|
|
local function populate_main_menu(buttons)
|
|
local ioport = manager.machine.ioport
|
|
local input = manager.machine.input
|
|
local menu = {}
|
|
menu[#menu + 1] = {_('Autofire buttons'), '', 'off'}
|
|
menu[#menu + 1] = {string.format(_('Press %s to delete'), input:seq_name(ioport:type_seq(ioport:token_to_input_type("UI_CLEAR")))), '', 'off'}
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
header_height = #menu
|
|
|
|
for index, button in ipairs(buttons) do
|
|
-- Assume refresh rate of 60 Hz; maybe better to use screen_device refresh()?
|
|
local rate = 60 / (button.on_frames + button.off_frames)
|
|
-- Round to two decimal places
|
|
rate = math.floor(rate * 100) / 100
|
|
local text = string.format(_('%s [%d Hz]'), _p("input-name", button.button.name), rate)
|
|
local subtext = input:seq_name(button.key)
|
|
menu[#menu + 1] = {text, subtext, ''}
|
|
end
|
|
content_height = #menu
|
|
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
menu[#menu + 1] = {_('Add autofire button'), '', ''}
|
|
return menu
|
|
end
|
|
|
|
local function handle_main_menu(index, event, buttons)
|
|
local section, adjusted_index = menu_section(index)
|
|
if section == MENU_SECTIONS.CONTENT then
|
|
if event == 'select' then
|
|
current_button = buttons[adjusted_index]
|
|
table.insert(menu_stack, MENU_TYPES.EDIT)
|
|
return true
|
|
elseif event == 'clear' then
|
|
table.remove(buttons, adjusted_index)
|
|
return true
|
|
end
|
|
elseif section == MENU_SECTIONS.FOOTER then
|
|
if event == 'select' then
|
|
current_button = create_new_button()
|
|
table.insert(menu_stack, MENU_TYPES.ADD)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Add/edit menus (mostly identical)
|
|
|
|
local function populate_configure_menu(menu)
|
|
local button_name = current_button.button and _p("input-name", current_button.button.name) or _('NOT SET')
|
|
local key_name = current_button.key and manager.machine.input:seq_name(current_button.key) or _('NOT SET')
|
|
menu[#menu + 1] = {_('Input'), button_name, ''}
|
|
menu[#menu + 1] = {_('Hotkey'), key_name, ''}
|
|
menu[#menu + 1] = {_('On frames'), current_button.on_frames, current_button.on_frames > 1 and 'lr' or 'r'}
|
|
menu[#menu + 1] = {_('Off frames'), current_button.off_frames, current_button.off_frames > 1 and 'lr' or 'r'}
|
|
end
|
|
|
|
-- Borrowed from the cheat plugin
|
|
local function poll_for_hotkey()
|
|
local input = manager.machine.input
|
|
local poller = input:switch_sequence_poller()
|
|
manager.machine:popmessage(_('Press button for hotkey or wait to leave unchanged'))
|
|
manager.machine.video:frame_update()
|
|
poller:start()
|
|
local time = os.clock()
|
|
local clearmsg = true
|
|
while (not poller:poll()) and (poller.modified or (os.clock() < time + 1)) do
|
|
if poller.modified then
|
|
if not poller.valid then
|
|
manager.machine:popmessage(_("Invalid sequence entered"))
|
|
clearmsg = false
|
|
break
|
|
end
|
|
manager.machine:popmessage(input:seq_name(poller.sequence))
|
|
manager.machine.video:frame_update()
|
|
end
|
|
end
|
|
if clearmsg then
|
|
manager.machine:popmessage()
|
|
end
|
|
return poller.valid and poller.sequence or nil
|
|
end
|
|
|
|
local function handle_configure_menu(index, event)
|
|
if index == 1 then
|
|
-- Input
|
|
if event == 'select' then
|
|
table.insert(menu_stack, MENU_TYPES.BUTTON)
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
elseif index == 2 then
|
|
-- Hotkey
|
|
if event == 'select' then
|
|
local keycode = poll_for_hotkey()
|
|
if keycode then
|
|
current_button.key = keycode
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
else
|
|
return false
|
|
end
|
|
elseif index == 3 then
|
|
-- On frames
|
|
manager.machine:popmessage(_('Number of frames button will be pressed'))
|
|
if event == 'left' then
|
|
current_button.on_frames = current_button.on_frames - 1
|
|
elseif event == 'right' then
|
|
current_button.on_frames = current_button.on_frames + 1
|
|
end
|
|
elseif index == 4 then
|
|
-- Off frames
|
|
manager.machine:popmessage(_('Number of frames button will be released'))
|
|
if event == 'left' then
|
|
current_button.off_frames = current_button.off_frames - 1
|
|
elseif event == 'right' then
|
|
current_button.off_frames = current_button.off_frames + 1
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function populate_edit_menu()
|
|
local menu = {}
|
|
menu[#menu + 1] = {_('Edit autofire button'), '', 'off'}
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
header_height = #menu
|
|
|
|
populate_configure_menu(menu)
|
|
content_height = #menu
|
|
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
menu[#menu + 1] = {_('Done'), '', ''}
|
|
return menu
|
|
end
|
|
|
|
local function handle_edit_menu(index, event, buttons)
|
|
local section, adjusted_index = menu_section(index)
|
|
if section == MENU_SECTIONS.CONTENT then
|
|
return handle_configure_menu(adjusted_index, event)
|
|
elseif section == MENU_SECTIONS.FOOTER then
|
|
if event == 'select' then
|
|
table.remove(menu_stack)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function populate_add_menu()
|
|
local menu = {}
|
|
menu[#menu + 1] = {_('Add autofire button'), '', 'off'}
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
header_height = #menu
|
|
|
|
populate_configure_menu(menu)
|
|
content_height = #menu
|
|
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
if is_button_complete(current_button) then
|
|
menu[#menu + 1] = {_('Create'), '', ''}
|
|
else
|
|
menu[#menu + 1] = {_('Cancel'), '', ''}
|
|
end
|
|
return menu
|
|
end
|
|
|
|
local function handle_add_menu(index, event, buttons)
|
|
local section, adjusted_index = menu_section(index)
|
|
if section == MENU_SECTIONS.CONTENT then
|
|
return handle_configure_menu(adjusted_index, event)
|
|
elseif section == MENU_SECTIONS.FOOTER then
|
|
if event == 'select' then
|
|
table.remove(menu_stack)
|
|
if is_button_complete(current_button) then
|
|
buttons[#buttons + 1] = current_button
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Button selection menu
|
|
|
|
local function populate_button_menu()
|
|
menu = {}
|
|
inputs = {}
|
|
menu[#menu + 1] = {_('Select an input for autofire'), '', 'off'}
|
|
menu[#menu + 1] = {'---', '', ''}
|
|
header_height = #menu
|
|
|
|
for port_key, port in pairs(manager.machine.ioport.ports) do
|
|
for field_key, field in pairs(port.fields) do
|
|
if is_supported_input(field) then
|
|
menu[#menu + 1] = { _p("input-name", field.name), '', '' }
|
|
inputs[#inputs + 1] = {
|
|
port_name = port_key,
|
|
field_name = field_key,
|
|
ioport_field = field
|
|
}
|
|
end
|
|
end
|
|
end
|
|
content_height = #menu
|
|
return menu
|
|
end
|
|
|
|
local function handle_button_menu(index, event)
|
|
local section, adjusted_index = menu_section(index)
|
|
if section == MENU_SECTIONS.CONTENT and event == 'select' then
|
|
local selected_input = inputs[adjusted_index]
|
|
current_button.port = selected_input.port_name
|
|
current_button.field = selected_input.field_name
|
|
current_button.button = selected_input.ioport_field
|
|
table.remove(menu_stack)
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function lib:init_menu(buttons)
|
|
header_height = 0
|
|
content_height = 0
|
|
menu_stack = { MENU_TYPES.MAIN }
|
|
current_button = {}
|
|
inputs = {}
|
|
end
|
|
|
|
function lib:populate_menu(buttons)
|
|
local current_menu = menu_stack[#menu_stack]
|
|
if current_menu == MENU_TYPES.MAIN then
|
|
return populate_main_menu(buttons)
|
|
elseif current_menu == MENU_TYPES.EDIT then
|
|
return populate_edit_menu()
|
|
elseif current_menu == MENU_TYPES.ADD then
|
|
return populate_add_menu()
|
|
elseif current_menu == MENU_TYPES.BUTTON then
|
|
return populate_button_menu()
|
|
end
|
|
end
|
|
|
|
function lib:handle_menu_event(index, event, buttons)
|
|
manager.machine:popmessage()
|
|
local current_menu = menu_stack[#menu_stack]
|
|
if current_menu == MENU_TYPES.MAIN then
|
|
return handle_main_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.EDIT then
|
|
return handle_edit_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.ADD then
|
|
return handle_add_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.BUTTON then
|
|
return handle_button_menu(index, event)
|
|
end
|
|
end
|
|
|
|
return lib
|