mame/plugins/portname/init.lua

175 lines
5 KiB
Lua

-- license:BSD-3-Clause
-- copyright-holders:Carl
-- data files are json files named <romname>.json
-- {
-- "import":"<import filename>"
-- "ports":{
-- "<ioport name>":{
-- "labels":{
-- "<field mask>":{
-- "player":<int player number>,
-- "name":"<field label>"
-- }
-- },{
-- ...
-- }
-- }
-- }
-- any additional metadata can be included for other usage
-- and will be ignored
local exports = {}
exports.name = "portname"
exports.version = "0.0.1"
exports.description = "IOPort name/translation plugin"
exports.license = "BSD-3-Clause"
exports.author = { name = "Carl" }
local portname = exports
function portname.startplugin()
local json = require("json")
local ctrlrpath = emu.subst_env(manager.options.entries.ctrlrpath:value():match("([^;]+)"))
local function get_filename(nosoft)
local filename
if emu.softname() ~= "" and not nosoft then
local soft = emu.softname():match("([^:]*)$")
filename = emu.romname() .. "_" .. soft .. ".json"
else
filename = emu.romname() .. ".json"
end
return filename
end
local function parse_names(ctable, depth)
if depth >= 5 then
emu.print_error("portname: max import depth exceeded")
return
end
if ctable.import then
local file = emu.file(ctrlrpath .. "/portname", "r")
local ret = file:open(ctable.import)
if not ret then
parse_names(json.parse(file:read(file:size())), depth + 1)
end
end
if not ctable.ports then
return
end
for pname, port in pairs(ctable.ports) do
local ioport = manager.machine.ioport.ports[pname]
if ioport then
for mask, label in pairs(port.labels) do
for num3, field in pairs(ioport.fields) do
local nummask = tonumber(mask, 16)
if nummask == field.mask and label.player == field.player then
field.live.name = label.name
end
end
end
end
end
end
emu.register_start(function()
local file = emu.file(ctrlrpath .. "/portname", "r")
local ret = file:open(get_filename())
if ret then
if emu.softname() ~= "" then
local parent
for tag, image in pairs(manager.machine.images) do
parent = image.software_parent
if parent then
break
end
end
if parent then
ret = file:open(emu.romname() .. "_" .. parent:match("([^:]*)$") .. ".json")
end
end
if ret then
ret = file:open(get_filename(true))
if ret then
ret = file:open(manager.machine.system.parent .. ".json")
if ret then
return
end
end
end
end
parse_names(json.parse(file:read(file:size())), 0)
end)
local function menu_populate()
return {{ _("Save input names to file"), "", 0 }}
end
local function menu_callback(index, event)
if event == "select" then
local ports = {}
for pname, port in pairs(manager.machine.ioport.ports) do
local labels = {}
local sort = {}
for fname, field in pairs(port.fields) do
local mask = string.format("%x", field.mask)
if not labels[mask] then
sort[#sort + 1] = mask
labels[mask] = { name = fname, player = field.player }
setmetatable(labels[mask], { __tojson = function(v,s)
local label = { name = v.name, player = v.player }
setmetatable(label, { __jsonorder = { "player", "name" }})
return json.stringify(label) end })
end
end
if #sort > 0 then
table.sort(sort, function(i, j) return tonumber(i, 16) < tonumber(j, 16) end)
setmetatable(labels, { __jsonorder = sort })
ports[pname] = { labels = labels }
end
end
local function check_path(path)
local attr = lfs.attributes(path)
if not attr then
lfs.mkdir(path)
if not lfs.attributes(path) then
manager.machine:popmessage(_("Failed to save input name file"))
emu.print_verbose("portname: unable to create path " .. path)
return false
end
elseif attr.mode ~= "directory" then
manager.machine:popmessage(_("Failed to save input name file"))
emu.print_verbose("portname: path exists but isn't directory " .. path)
return false
end
return true
end
if not check_path(ctrlrpath) then
return false
end
if not check_path(ctrlrpath .. "/portname") then
return false
end
local filename = get_filename()
local file = io.open(ctrlrpath .. "/portname/" .. filename, "r")
if file then
emu.print_verbose("portname: input name file exists " .. filename)
manager.machine:popmessage(_("Failed to save input name file"))
file:close()
return false
end
file = io.open(ctrlrpath .. "/portname/" .. filename, "w")
local ctable = { romname = emu.romname(), ports = ports }
if emu.softname() ~= "" then
ctable.softname = emu.softname()
end
setmetatable(ctable, { __jsonorder = { "romname", "softname", "ports" }})
file:write(json.stringify(ctable, { indent = true }))
file:close()
manager.machine:popmessage(string.format(_("Input port name file saved to %s"), ctrlrpath .. "/portname/" .. filename))
end
return false
end
emu.register_menu(menu_callback, menu_populate, _("Input ports"))
end
return exports