diff options
Diffstat (limited to 'plugins/hiscore/init.lua')
-rw-r--r-- | plugins/hiscore/init.lua | 177 |
1 files changed, 119 insertions, 58 deletions
diff --git a/plugins/hiscore/init.lua b/plugins/hiscore/init.lua index ded3f0e44d2..8b8dd6c6d23 100644 --- a/plugins/hiscore/init.lua +++ b/plugins/hiscore/init.lua @@ -1,19 +1,21 @@ -- hiscore.lua --- by borgar@borgar.net, WTFPL license +-- by borgar@borgar.net, CC0 license -- --- This uses MAME's built-in Lua scripting to implment +-- This uses MAME's built-in Lua scripting to implement -- high-score saving with hiscore.dat infom just as older -- builds did in the past. -- -local exports = {} -exports.name = "hiscore" -exports.version = "1.0.0" -exports.description = "Hiscore" -exports.license = "WTFPL license" -exports.author = { name = "borgar@borgar.net" } +local exports = { + name = 'hiscore', + version = '1.0.1', + description = 'Hiscore', + license = 'CC0', + author = { name = 'borgar@borgar.net' } } + local hiscore = exports -local hiscore_plugin_path = "" +local hiscore_plugin_path +local reset_subscription, frame_subscription, stop_subscription function hiscore.set_folder(path) hiscore_plugin_path = path @@ -21,44 +23,97 @@ end function hiscore.startplugin() + local function get_data_path() + return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/hiscore' + end + + -- configuration + local config_read = false + local timed_save = true + + -- read configuration file from data directory + local function read_config() + if config_read then + return true + end + local filename = get_data_path() .. '/plugin.cfg' + local file = io.open(filename, 'r') + if file then + local json = require('json') + local parsed_settings = json.parse(file:read('a')) + file:close() + if parsed_settings then + if parsed_settings.only_save_at_exit and (parsed_settings.only_save_at_exit ~= 0) then + timed_save = false + end + -- TODO: other settings? maybe path overrides for hiscore.dat or the hiscore data? + config_read = true + return true + else + emu.print_error(string.format('Error loading hiscore plugin settings: error parsing file "%s" as JSON', filename)) + end + end + return false + end + + -- save configuration file + local function save_config() + local path = get_data_path() + local attr = lfs.attributes(path) + if not attr then + lfs.mkdir(path) + elseif attr.mode ~= 'directory' then + emu.print_error(string.format('Error saving hiscore plugin settings: "%s" is not a directory', path)) + return + end + local settings = { only_save_at_exit = not timed_save } + -- TODO: other settings? + local filename = path .. '/plugin.cfg' + local json = require('json') + local data = json.stringify(settings, { indent = true }) + local file = io.open(filename, 'w') + if not file then + emu.print_error(string.format('Error saving hiscore plugin settings: error opening file "%s" for writing', filename)) + return + end + file:write(data) + file:close() + end + + -- build menu + local function populate_menu() + local items = { } + local setting = timed_save and _p('plugin-hiscore', 'When updated') or _p('plugin-hiscore', 'On exit') + table.insert(items, { _p('plugin-hiscore', 'Hiscore Support Options'), '', 'off' }) + table.insert(items, { '---', '', '' }) + table.insert(items, { _p('plugin-hiscore', 'Save scores'), setting, timed_save and 'l' or 'r' }) + return items + end + + -- handle menu events + local function handle_menu(index, event) + if event == 'left' then + timed_save = false + return true + elseif event == 'right' then + timed_save = true + return true + end + return false + end + local hiscoredata_path = "hiscore.dat"; - local hiscore_path = "hi"; - local config_path = lfs.env_replace(manager:options().entries.inipath:value():match("[^;]+") .. "/hiscore.ini"); local current_checksum = 0; local default_checksum = 0; - local config_read = false; local scores_have_been_read = false; local mem_check_passed = false; local found_hiscore_entry = false; - local timed_save = true; local delaytime = 0; - local positions = {}; - -- Configuration file will be searched in the first path defined - -- in mame inipath option. - local function read_config() - if config_read then return true end; - local file = io.open( config_path, "r" ); - if file then - file:close() - emu.print_verbose( "hiscore: config found" ); - local _conf = {} - for line in io.lines(config_path) do - token, value = string.match(line, '([^ ]+) ([^ ]+)'); - _conf[token] = value; - end - hiscore_path = lfs.env_replace(_conf["hi_path"] or hiscore_path); - timed_save = _conf["only_save_at_exit"] ~= "1" - -- hiscoredata_path = _conf["dat_path"]; -- don't know if I should do it, but wathever - return true - end - return false - end - local function parse_table ( dsting ) - local _table = {}; + local _table = {} for line in string.gmatch(dsting, '([^\n]+)') do local delay = line:match('^@delay=([.%d]*)') if delay and #delay > 0 then @@ -66,13 +121,13 @@ function hiscore.startplugin() else local cpu, mem; local cputag, space, offs, len, chk_st, chk_ed, fill = string.match(line, '^@([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),?(%x?%x?)'); - cpu = manager:machine().devices[cputag]; + cpu = manager.machine.devices[cputag]; if not cpu then error(cputag .. " device not found") end local rgnname, rgntype = space:match("([^/]*)/?([^/]*)") if rgntype == "share" then - mem = manager:machine():memory().shares[rgnname] + mem = manager.machine.memory.shares[rgnname] else mem = cpu.spaces[space] end @@ -120,7 +175,7 @@ function hiscore.startplugin() end elseif string.find(line, rm_match) then --- match this game current_is_match = true; - elseif string.find(line, '^[a-z0-9_]+:') then --- some game + elseif string.find(line, '^[a-z0-9_,]+:') then --- some game if current_is_match and string.len(cluster) > 0 then break; -- we're done end @@ -152,13 +207,13 @@ function hiscore.startplugin() end - local function get_file_name () + local function get_file_name() local r; if emu.softname() ~= "" then local soft = emu.softname():match("([^:]*)$") - r = hiscore_path .. '/' .. emu.romname() .. "_" .. soft .. ".hi"; + r = get_data_path() .. '/' .. emu.romname() .. "_" .. soft .. ".hi"; else - r = hiscore_path .. '/' .. emu.romname() .. ".hi"; + r = get_data_path() .. '/' .. emu.romname() .. ".hi"; end return r; end @@ -169,13 +224,13 @@ function hiscore.startplugin() local output = io.open(get_file_name(), "wb"); if not output then -- attempt to create the directory, and try again - lfs.mkdir( hiscore_path ); + lfs.mkdir(get_data_path()); output = io.open(get_file_name(), "wb"); end emu.print_verbose("hiscore: write_scores output") if output then for ri,row in ipairs(posdata) do - t = {}; + t = {} for i=0,row["size"]-1 do t[i+1] = row["mem"]:read_u8(row["addr"] + i) end @@ -262,25 +317,25 @@ function hiscore.startplugin() end local function reset() - -- the notifier will still be attached even if the running game has no hiscore.dat entry - if mem_check_passed and found_hiscore_entry then - local checksum = check_scores(positions) - if checksum ~= current_checksum and checksum ~= default_checksum then - write_scores(positions) + -- the notifier will still be attached even if the running game has no hiscore.dat entry + if mem_check_passed and found_hiscore_entry then + local checksum = check_scores(positions) + if checksum ~= current_checksum and checksum ~= default_checksum then + write_scores(positions) + end end - end - found_hiscore_entry = false - mem_check_passed = false - scores_have_been_read = false; + found_hiscore_entry = false + mem_check_passed = false + scores_have_been_read = false; end - emu.register_start(function() + reset_subscription = emu.add_machine_reset_notifier(function () found_hiscore_entry = false mem_check_passed = false scores_have_been_read = false; last_write_time = -10 emu.print_verbose("Starting " .. emu.gamename()) - config_read = read_config(); + read_config(); local dat = read_hiscore_dat() if dat and dat ~= "" then emu.print_verbose( "hiscore: found hiscore.dat entry for " .. emu.romname() ); @@ -299,17 +354,23 @@ function hiscore.startplugin() found_hiscore_entry = true end end) - emu.register_frame(function() + + frame_subscription = emu.add_machine_frame_notifier(function () if found_hiscore_entry then tick() end end) - emu.register_stop(function() + + stop_subscription = emu.add_machine_stop_notifier(function () reset() + save_config() end) - emu.register_prestart(function() + + emu.register_prestart(function () reset() end) + + emu.register_menu(handle_menu, populate_menu, _p('plugin-hiscore', 'Hiscore Support')) end return exports |