mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
plugins: Rewrote timer plugin fixing multiple issues.
Added emulated time recording as well as wall clock time. Fixed recording time for multiple software items per system. An incorrect constraint on the database table meant that time was only being recorded for a single software item per system. Detect the "empty" driver so the time spent at the selection menu isn't recorded (you'd get multiple entries for this due to the way options leak when returning to the system selection menu). Included schema migration code to update existing timer plugin databases. Also replaced some unnecessary floating point code with integer maths, added log messages, and made the plugin unload unload its database access code during emulation. Changed other plugins' use of paths with trailing slashes as this causes stat to fail on Windows.
This commit is contained in:
parent
3bb8e3adc7
commit
07e55935cf
@ -1,7 +1,7 @@
|
||||
.. _plugins-timer:
|
||||
|
||||
Timer Plugin
|
||||
============
|
||||
Game Play Timer Plugin
|
||||
======================
|
||||
|
||||
The timer plugin records the total time spent emulating each combination of a
|
||||
system and a software list item, as well as the number of times each combination
|
||||
@ -9,12 +9,12 @@ has been launched. To see the statistics, bring up the main menu (press **Tab**
|
||||
during emulation by default), choose **Plugin Options**, and then choose
|
||||
**Timer**.
|
||||
|
||||
Note that this plugin records wall clock time, not emulated time. That is, it
|
||||
records the real time duration elapsed while the emulation is running, according
|
||||
to the host OS. This may be shorter than the elapsed emulated time if you turn
|
||||
off throttling or use MAME’s “fast forward” feature, or it may be longer than
|
||||
the elapsed emulated time if you pause the emulation of if the emulation is too
|
||||
demanding to run at full speed.
|
||||
This plugin records wall clock time (the real time duration elapsed while
|
||||
emulation is running, according to the host OS) as well as emulated time. The
|
||||
elapsed wall clock time may be shorter than the elapsed emulated time if you
|
||||
turn off throttling or use MAME’s “fast forward” feature, or it may be longer
|
||||
than the elapsed emulated time if you pause the emulation of if the emulation is
|
||||
too demanding to run at full speed.
|
||||
|
||||
The statistics are stored in the file **timer.db** in the **timer** folder
|
||||
inside your plugin data folder (see the
|
||||
|
@ -1,7 +1,7 @@
|
||||
local lib = {}
|
||||
|
||||
local function get_settings_path()
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/autofire/'
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/autofire'
|
||||
end
|
||||
|
||||
local function get_settings_filename()
|
||||
@ -52,7 +52,7 @@ end
|
||||
function lib:load_settings()
|
||||
local buttons = {}
|
||||
local json = require('json')
|
||||
local filename = get_settings_path() .. get_settings_filename()
|
||||
local filename = get_settings_path() .. '/' .. get_settings_filename()
|
||||
local file = io.open(filename, 'r')
|
||||
if not file then
|
||||
return buttons
|
||||
@ -81,14 +81,14 @@ function lib:save_settings(buttons)
|
||||
emu.print_error(string.format('Error saving autofire settings: "%s" is not a directory', path))
|
||||
return
|
||||
end
|
||||
local filename = path .. '/' .. get_settings_filename()
|
||||
if #buttons == 0 then
|
||||
os.remove(path .. get_settings_filename())
|
||||
os.remove(filename)
|
||||
return
|
||||
end
|
||||
local json = require('json')
|
||||
local settings = serialize_settings(buttons)
|
||||
local data = json.stringify(settings, {indent = true})
|
||||
local filename = path .. get_settings_filename()
|
||||
local file = io.open(filename, 'w')
|
||||
if not file then
|
||||
emu.print_error(string.format('Error saving autofire settings: error opening file "%s" for writing', filename))
|
||||
|
@ -23,7 +23,7 @@ end
|
||||
function hiscore.startplugin()
|
||||
|
||||
local function get_data_path()
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/hiscore/'
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/hiscore'
|
||||
end
|
||||
|
||||
-- configuration
|
||||
@ -35,7 +35,7 @@ function hiscore.startplugin()
|
||||
if config_read then
|
||||
return true
|
||||
end
|
||||
local filename = get_data_path() .. 'plugin.cfg'
|
||||
local filename = get_data_path() .. '/plugin.cfg'
|
||||
local file = io.open(filename, 'r')
|
||||
if file then
|
||||
local json = require('json')
|
||||
@ -67,7 +67,7 @@ function hiscore.startplugin()
|
||||
end
|
||||
local settings = { only_save_at_exit = not timed_save }
|
||||
-- TODO: other settings?
|
||||
local filename = path .. 'plugin.cfg'
|
||||
local filename = path .. '/plugin.cfg'
|
||||
local json = require('json')
|
||||
local data = json.stringify(settings, { indent = true })
|
||||
local file = io.open(filename, 'w')
|
||||
@ -210,9 +210,9 @@ function hiscore.startplugin()
|
||||
local r;
|
||||
if emu.softname() ~= "" then
|
||||
local soft = emu.softname():match("([^:]*)$")
|
||||
r = get_data_path() .. emu.romname() .. "_" .. soft .. ".hi";
|
||||
r = get_data_path() .. '/' .. emu.romname() .. "_" .. soft .. ".hi";
|
||||
else
|
||||
r = get_data_path() .. emu.romname() .. ".hi";
|
||||
r = get_data_path() .. '/' .. emu.romname() .. ".hi";
|
||||
end
|
||||
return r;
|
||||
end
|
||||
@ -223,7 +223,7 @@ 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( get_data_path() );
|
||||
lfs.mkdir(get_data_path());
|
||||
output = io.open(get_file_name(), "wb");
|
||||
end
|
||||
emu.print_verbose("hiscore: write_scores output")
|
||||
|
@ -5,7 +5,7 @@
|
||||
-- Helpers
|
||||
|
||||
local function settings_path()
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/inputmacro/'
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/inputmacro'
|
||||
end
|
||||
|
||||
local function settings_filename()
|
||||
@ -101,7 +101,7 @@ end
|
||||
local lib = { }
|
||||
|
||||
function lib:load_settings()
|
||||
filename = settings_path() .. settings_filename()
|
||||
filename = settings_path() .. '/' .. settings_filename()
|
||||
local file = io.open(filename, 'r')
|
||||
if not file then
|
||||
return { }
|
||||
@ -133,7 +133,7 @@ function lib:save_settings(macros)
|
||||
emu.print_error(string.format('Error saving input macros: "%s" is not a directory', path))
|
||||
return
|
||||
end
|
||||
filename = path .. settings_filename()
|
||||
filename = path .. '/' .. settings_filename()
|
||||
|
||||
if #macros == 0 then
|
||||
os.remove(filename)
|
||||
|
@ -34,7 +34,7 @@ function timecode.startplugin()
|
||||
|
||||
|
||||
local function get_settings_path()
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/timecode/'
|
||||
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/timecode'
|
||||
end
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ function timecode.startplugin()
|
||||
set_default_hotkey()
|
||||
|
||||
-- try to open configuration file
|
||||
local cfgname = get_settings_path() .. 'plugin.cfg'
|
||||
local cfgname = get_settings_path() .. '/plugin.cfg'
|
||||
local cfgfile = io.open(cfgname, 'r')
|
||||
if not cfgfile then
|
||||
return -- probably harmless, configuration just doesn't exist yet
|
||||
@ -97,7 +97,7 @@ function timecode.startplugin()
|
||||
settings.hotkey = hotkey_cfg
|
||||
end
|
||||
local data = json.stringify(settings, { indent = true })
|
||||
local cfgname = path .. 'plugin.cfg'
|
||||
local cfgname = path .. '/plugin.cfg'
|
||||
local cfgfile = io.open(cfgname, 'w')
|
||||
if not cfgfile then
|
||||
emu.print_error(string.format('Error saving timecode recorder settings: error opening file "%s" for writing', cfgname))
|
||||
|
@ -1,111 +1,73 @@
|
||||
-- license:BSD-3-Clause
|
||||
-- copyright-holders:Carl
|
||||
require('lfs')
|
||||
local sqlite3 = require('lsqlite3')
|
||||
local exports = {}
|
||||
exports.name = "timer"
|
||||
exports.version = "0.0.2"
|
||||
exports.description = "Game play timer"
|
||||
exports.license = "BSD-3-Clause"
|
||||
exports.author = { name = "Carl" }
|
||||
-- copyright-holders:Vas Crabb
|
||||
local exports = {
|
||||
name = 'timer',
|
||||
version = '0.0.3',
|
||||
description = 'Game play timer',
|
||||
license = 'BSD-3-Clause',
|
||||
author = { name = 'Vas Crabb' } }
|
||||
|
||||
local timer = exports
|
||||
|
||||
function timer.startplugin()
|
||||
local dir = emu.subst_env(manager.options.entries.homepath:value())
|
||||
local timer_db = dir .. "/timer/timer.db"
|
||||
local timer_started = false
|
||||
local total_time = 0
|
||||
local start_time = 0
|
||||
local play_count = 0
|
||||
local emu_total = emu.attotime()
|
||||
|
||||
local function save()
|
||||
total_time = total_time + (os.time() - start_time)
|
||||
local reference = 0
|
||||
local lastupdate
|
||||
|
||||
local db = assert(sqlite3.open(timer_db))
|
||||
|
||||
local insert_stmt = assert( db:prepare("INSERT OR IGNORE INTO timer VALUES (?, ?, 0, 0)") )
|
||||
insert_stmt:bind_values(emu.romname(), emu.softname())
|
||||
insert_stmt:step()
|
||||
insert_stmt:reset()
|
||||
|
||||
local update_stmt = assert( db:prepare("UPDATE timer SET total_time=?, play_count=? WHERE driver=? AND software=?") )
|
||||
update_stmt:bind_values(total_time, play_count,emu.romname(), emu.softname())
|
||||
update_stmt:step()
|
||||
update_stmt:reset()
|
||||
|
||||
assert(db:close() == sqlite3.OK)
|
||||
end
|
||||
|
||||
|
||||
emu.register_start(function()
|
||||
local file
|
||||
if timer_started then
|
||||
save()
|
||||
end
|
||||
timer_started = true
|
||||
lfs.mkdir(dir .. '/timer')
|
||||
local db = assert(sqlite3.open(timer_db))
|
||||
local found=false
|
||||
db:exec([[select * from sqlite_master where name='timer';]], function(...) found=true return 0 end)
|
||||
if not found then
|
||||
db:exec[[ CREATE TABLE timer (
|
||||
driver VARCHAR(32) PRIMARY KEY,
|
||||
software VARCHAR(40),
|
||||
total_time INTEGER NOT NULL,
|
||||
play_count INTEGER NOT NULL
|
||||
); ]]
|
||||
end
|
||||
|
||||
local stmt, row
|
||||
stmt = db:prepare("SELECT total_time, play_count FROM timer WHERE driver = ? AND software = ?")
|
||||
stmt:bind_values(emu.romname(), emu.softname())
|
||||
if (stmt:step() == sqlite3.ROW) then
|
||||
row = stmt:get_named_values()
|
||||
play_count = row.play_count
|
||||
total_time = row.total_time
|
||||
else
|
||||
play_count = 0
|
||||
total_time = 0
|
||||
end
|
||||
|
||||
assert(db:close() == sqlite3.OK)
|
||||
|
||||
start_time = os.time()
|
||||
play_count = play_count + 1
|
||||
end)
|
||||
|
||||
emu.register_stop(function()
|
||||
timer_started = false
|
||||
save()
|
||||
total_time = 0
|
||||
play_count = 0
|
||||
end)
|
||||
|
||||
local function sectohms(time)
|
||||
local hrs = math.floor(time / 3600)
|
||||
local min = math.floor((time % 3600) / 60)
|
||||
local hrs = time // 3600
|
||||
local min = (time % 3600) // 60
|
||||
local sec = time % 60
|
||||
return string.format(_p("plugin-timer", "%03d:%02d:%02d"), hrs, min, sec)
|
||||
return string.format(_p('plugin-timer', '%03d:%02d:%02d'), hrs, min, sec)
|
||||
end
|
||||
|
||||
local lastupdate
|
||||
|
||||
local function menu_populate()
|
||||
lastupdate = os.time()
|
||||
local time = lastupdate - start_time
|
||||
local refname = (reference == 0) and _p('plugin-timer', 'Wall clock') or _p('plugin-timer', 'Emulated time')
|
||||
local time = (reference == 0) and (lastupdate - start_time) or manager.machine.time.seconds
|
||||
local total = (reference == 0) and (total_time + time) or (manager.machine.time + emu_total).seconds
|
||||
return
|
||||
{{ _p("plugin-timer", "Current time"), sectohms(time), "off" },
|
||||
{ _p("plugin-timer", "Total time"), sectohms(total_time + time), "off" },
|
||||
{ _p("plugin-timer", "Play Count"), play_count, "off" }},
|
||||
{
|
||||
{ _p("plugin-timer", "Reference"), refname, (reference == 0) and 'r' or 'l' },
|
||||
{ '---', '', '' },
|
||||
{ _p("plugin-timer", "Current time"), sectohms(time), "off" },
|
||||
{ _p("plugin-timer", "Total time"), sectohms(total), "off" },
|
||||
{ _p("plugin-timer", "Play Count"), play_count, "off" } },
|
||||
nil,
|
||||
"idle"
|
||||
end
|
||||
|
||||
local function menu_callback(index, event)
|
||||
if (index == 1) and ((event == 'left') or (event == 'right') or (event == 'select')) then
|
||||
reference = reference ~ 1
|
||||
return true
|
||||
end
|
||||
return os.time() > lastupdate
|
||||
end
|
||||
|
||||
|
||||
emu.register_start(
|
||||
function()
|
||||
if emu.romname() ~= '___empty' then
|
||||
start_time = os.time()
|
||||
local persister = require('timer/timer_persist')
|
||||
total_time, play_count, emu_total = persister:start_session()
|
||||
end
|
||||
end)
|
||||
|
||||
emu.register_stop(
|
||||
function()
|
||||
if emu.romname() ~= '___empty' then
|
||||
local persister = require('timer/timer_persist')
|
||||
persister:update_totals(start_time)
|
||||
end
|
||||
end)
|
||||
|
||||
emu.register_menu(menu_callback, menu_populate, _p("plugin-timer", "Timer"))
|
||||
end
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"plugin": {
|
||||
"name": "timer",
|
||||
"description": "Timer plugin",
|
||||
"version": "0.0.1",
|
||||
"author": "Carl",
|
||||
"type": "plugin",
|
||||
"start": "false"
|
||||
}
|
||||
"plugin": {
|
||||
"name": "timer",
|
||||
"description": "Game play timer",
|
||||
"version": "0.0.3",
|
||||
"author": "Vas Crabb",
|
||||
"type": "plugin",
|
||||
"start": "false"
|
||||
}
|
||||
}
|
||||
|
249
plugins/timer/timer_persist.lua
Normal file
249
plugins/timer/timer_persist.lua
Normal file
@ -0,0 +1,249 @@
|
||||
-- license:BSD-3-Clause
|
||||
-- copyright-holders:Vas Crabb
|
||||
|
||||
local sqlite3 = require('lsqlite3')
|
||||
|
||||
|
||||
local function check_schema(db)
|
||||
local create_statement =
|
||||
[[CREATE TABLE timer (
|
||||
driver VARCHAR(32) NOT NULL,
|
||||
softlist VARCHAR(24) NOT NULL DEFAULT '',
|
||||
software VARCHAR(16) NOT NULL DEFAULT '',
|
||||
total_time INTEGER NOT NULL DEFAULT 0,
|
||||
play_count INTEGER NOT NULL DEFAULT 0,
|
||||
emu_sec INTEGER NOT NULL DEFAULT 0,
|
||||
emu_nsec INTEGER NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (driver, softlist, software));]]
|
||||
|
||||
-- create table if it doesn't exist yet
|
||||
local table_found = false
|
||||
db:exec(
|
||||
[[SELECT * FROM sqlite_master WHERE type = 'table' AND name='timer';]],
|
||||
function()
|
||||
table_found = true
|
||||
end)
|
||||
if not table_found then
|
||||
emu.print_verbose('Creating timer database table')
|
||||
db:exec(create_statement)
|
||||
return
|
||||
end
|
||||
|
||||
-- check recently added columns
|
||||
local have_softlist = false
|
||||
local have_emu_sec = false
|
||||
local have_emu_nsec = false
|
||||
db:exec(
|
||||
[[PRAGMA table_info(timer);]],
|
||||
function(udata, n, vals, cols)
|
||||
for i, name in ipairs(cols) do
|
||||
if name == 'name' then
|
||||
if vals[i] == 'softlist' then
|
||||
have_softlist = true
|
||||
elseif vals[i] == 'emu_sec' then
|
||||
have_emu_sec = true
|
||||
elseif vals[i] == 'emu_nsec' then
|
||||
have_emu_nsec = true
|
||||
end
|
||||
return 0
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end)
|
||||
if not have_softlist then
|
||||
emu.print_verbose('Adding softlist column to timer database')
|
||||
db:exec([[ALTER TABLE timer ADD COLUMN softlist VARCHAR(24) NOT NULL DEFAULT '';]])
|
||||
local to_split = { }
|
||||
db:exec(
|
||||
[[SELECT DISTINCT software FROM timer WHERE software LIKE '%:%';]],
|
||||
function(udata, n, vals)
|
||||
table.insert(to_split, vals[1])
|
||||
return 0
|
||||
end)
|
||||
if #to_split > 0 then
|
||||
local update = db:prepare([[UPDATE timer SET softlist = ?, software = ? WHERE software = ?;]])
|
||||
for i, softname in ipairs(to_split) do
|
||||
local x, y = softname:find(':')
|
||||
local softlist = softname:sub(1, x - 1)
|
||||
local software = softname:sub(y + 1)
|
||||
update:bind_values(softlist, software, softname)
|
||||
update:step()
|
||||
update:reset()
|
||||
end
|
||||
end
|
||||
end
|
||||
if not have_emu_sec then
|
||||
emu.print_verbose('Adding emu_sec column to timer database')
|
||||
db:exec([[ALTER TABLE timer ADD COLUMN emu_sec INTEGER NOT NULL DEFAULT 0;]])
|
||||
end
|
||||
if not have_emu_nsec then
|
||||
emu.print_verbose('Adding emu_nsec column to timer database')
|
||||
db:exec([[ALTER TABLE timer ADD COLUMN emu_nsec INTEGER NOT NULL DEFAULT 0;]])
|
||||
end
|
||||
|
||||
-- check the required columns are in the primary key
|
||||
local index_name
|
||||
db:exec(
|
||||
[[SELECT name FROM sqlite_master WHERE type = 'index' AND tbl_name = 'timer';]],
|
||||
function(udata, n, vals)
|
||||
index_name = vals[1]
|
||||
end)
|
||||
local index_good
|
||||
if index_name then
|
||||
local driver_indexed = false
|
||||
local softlist_indexed = false
|
||||
local software_indexed = false
|
||||
db:exec(
|
||||
string.format([[PRAGMA index_info('%s');]], index_name), -- can't use prepared statement for PRAGMA
|
||||
function(udata, n, vals, cols)
|
||||
for i, name in ipairs(cols) do
|
||||
if name == 'name' then
|
||||
if vals[i] == 'driver' then
|
||||
driver_indexed = true
|
||||
elseif vals[i] == 'softlist' then
|
||||
softlist_indexed = true
|
||||
elseif vals[i] == 'software' then
|
||||
software_indexed = true
|
||||
end
|
||||
return 0
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end)
|
||||
index_good = driver_indexed and softlist_indexed and software_indexed
|
||||
end
|
||||
|
||||
-- if the required columns are not indexed, migrate to a new table with desired primary key
|
||||
if not index_good then
|
||||
emu.print_verbose('Re-indexing timer database table')
|
||||
db:exec([[DROP TABLE IF EXISTS timer_old;]])
|
||||
db:exec([[ALTER TABLE timer RENAME TO timer_old;]])
|
||||
db:exec(create_statement)
|
||||
db:exec(
|
||||
[[INSERT
|
||||
INTO timer (driver, softlist, software, total_time, play_count, emu_sec, emu_nsec)
|
||||
SELECT driver, softlist, software, total_time, play_count, emu_sec, emu_nsec FROM timer_old;]])
|
||||
db:exec([[DROP TABLE timer_old;]])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function open_database()
|
||||
-- make sure settings directory exists
|
||||
local dir = emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/timer'
|
||||
local attr = lfs.attributes(dir)
|
||||
if not attr then
|
||||
lfs.mkdir(dir)
|
||||
elseif attr.mode ~= 'directory' then
|
||||
emu.print_error(string.format('Error opening timer database: "%s" is not a directory', dir))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- open database
|
||||
local filename = dir .. '/timer.db'
|
||||
local db = sqlite3.open(filename)
|
||||
if not db then
|
||||
emu.print_error(string.format('Error opening timer database file "%s"', filename))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- make sure schema is up-to-date
|
||||
check_schema(db)
|
||||
return db
|
||||
end
|
||||
|
||||
|
||||
local function get_software()
|
||||
local softname = emu.softname()
|
||||
local i, j = softname:find(':')
|
||||
if i then
|
||||
return softname:sub(1, i - 1), softname:sub(j + 1)
|
||||
else
|
||||
-- FIXME: need a way to get the implicit software list when no colon in the option value
|
||||
return '', softname
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function get_current(db)
|
||||
local statement = db:prepare(
|
||||
[[SELECT
|
||||
total_time, play_count, emu_sec, emu_nsec
|
||||
FROM timer
|
||||
WHERE driver = ? AND softlist = ? AND software = ?;]])
|
||||
statement:bind_values(emu.romname(), get_software())
|
||||
local result
|
||||
if statement:step() == sqlite3.ROW then
|
||||
result = statement:get_named_values()
|
||||
end
|
||||
statement:reset()
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
local lib = { }
|
||||
|
||||
function lib:start_session()
|
||||
-- open database
|
||||
local db = open_database()
|
||||
if not db then
|
||||
return 0, 0, emu.attotime()
|
||||
end
|
||||
|
||||
-- get existing values
|
||||
local row = get_current(db)
|
||||
local update
|
||||
if row then
|
||||
update = db:prepare(
|
||||
[[UPDATE timer
|
||||
SET play_count = play_count + 1
|
||||
WHERE driver = ? AND softlist = ? AND software = ?;]])
|
||||
else
|
||||
row = { total_time = 0, play_count = 0, emu_sec = 0, emu_nsec = 0 }
|
||||
update = db:prepare(
|
||||
[[INSERT
|
||||
INTO timer (driver, softlist, software, total_time, play_count, emu_sec, emu_nsec)
|
||||
VALUES (?, ?, ?, 0, 1, 0, 0);]])
|
||||
end
|
||||
update:bind_values(emu.romname(), get_software())
|
||||
update:step()
|
||||
update:reset()
|
||||
return row.total_time, row.play_count + 1, emu.attotime.from_seconds(row.emu_sec) + emu.attotime.from_nsec(row.emu_nsec)
|
||||
end
|
||||
|
||||
function lib:update_totals(start)
|
||||
-- open database
|
||||
local db = open_database()
|
||||
if not db then
|
||||
return
|
||||
end
|
||||
|
||||
-- get existing values
|
||||
local row = get_current(db)
|
||||
if not row then
|
||||
row = { total_time = 0, play_count = 1, emu_sec = 0, emu_nsec = 0 }
|
||||
end
|
||||
|
||||
-- calculate new totals
|
||||
local emu_total = emu.attotime.from_seconds(row.emu_sec) + emu.attotime.from_nsec(row.emu_nsec) + manager.machine.time
|
||||
row.total_time = os.time() - start + row.total_time
|
||||
row.emu_sec = emu_total.seconds
|
||||
row.emu_nsec = emu_total.nsec
|
||||
|
||||
-- update database
|
||||
local update = db:prepare(
|
||||
[[INSERT OR REPLACE
|
||||
INTO timer (driver, softlist, software, total_time, play_count, emu_sec, emu_nsec)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?);]])
|
||||
local softlist, software = get_software()
|
||||
update:bind_values(emu.romname(), softlist, software, row.total_time, row.play_count, row.emu_sec, row.emu_nsec)
|
||||
update:step()
|
||||
update:reset()
|
||||
|
||||
-- close database
|
||||
if db:close() ~= sqlite3.OK then
|
||||
emu.print_error('Error closing timer database')
|
||||
end
|
||||
end
|
||||
|
||||
return lib
|
Loading…
Reference in New Issue
Block a user