mirror of
https://github.com/Abdess/retrobios.git
synced 2026-06-26 04:52:47 +00:00
expand bios collection, retrobat at 93% coverage
This commit is contained in:
parent
851a14e49a
commit
e6ea0484a8
3946 changed files with 8119839 additions and 2930936 deletions
245
bios/Arcade/MAME/plugins/data/button_char.lua
Normal file
245
bios/Arcade/MAME/plugins/data/button_char.lua
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
local default_text =
|
||||
{
|
||||
-- Alphabetic Buttons (NeoGeo): A~D,H,Z
|
||||
["A"] = 1, -- BTN_A
|
||||
["B"] = 2, -- BTN_B
|
||||
["C"] = 3, -- BTN_C
|
||||
["D"] = 4, -- BTN_D
|
||||
["H"] = 8, -- BTN_H
|
||||
["Z"] = 26, -- BTN_Z
|
||||
-- Numerical Buttons (Capcom): 1~10
|
||||
["a"] = 27, -- BTN_1
|
||||
["b"] = 28, -- BTN_2
|
||||
["c"] = 29, -- BTN_3
|
||||
["d"] = 30, -- BTN_4
|
||||
["e"] = 31, -- BTN_5
|
||||
["f"] = 32, -- BTN_6
|
||||
["g"] = 33, -- BTN_7
|
||||
["h"] = 34, -- BTN_8
|
||||
["i"] = 35, -- BTN_9
|
||||
["j"] = 36, -- BTN_10
|
||||
-- Directions of Arrow, Joystick Ball
|
||||
["+"] = 39, -- BTN_+
|
||||
["."] = 40, -- DIR_...
|
||||
["1"] = 41, -- DIR_1
|
||||
["2"] = 42, -- DIR_2
|
||||
["3"] = 43, -- DIR_3
|
||||
["4"] = 44, -- DIR_4
|
||||
["5"] = 45, -- Joystick Ball
|
||||
["6"] = 46, -- DIR_6
|
||||
["7"] = 47, -- DIR_7
|
||||
["8"] = 48, -- DIR_8
|
||||
["9"] = 49, -- DIR_9
|
||||
["N"] = 50, -- DIR_N
|
||||
-- Special Buttons
|
||||
["S"] = 51, -- BTN_START
|
||||
["P"] = 53, -- BTN_PUNCH
|
||||
["K"] = 54, -- BTN_KICK
|
||||
["G"] = 55, -- BTN_GUARD
|
||||
-- Composition of Arrow Directions
|
||||
["!"] = 90, -- Arrow
|
||||
["k"] = 100, -- Half Circle Back
|
||||
["l"] = 101, -- Half Circle Front Up
|
||||
["m"] = 102, -- Half Circle Front
|
||||
["n"] = 103, -- Half Circle Back Up
|
||||
["o"] = 104, -- 1/4 Cir For 2 Down
|
||||
["p"] = 105, -- 1/4 Cir Down 2 Back
|
||||
["q"] = 106, -- 1/4 Cir Back 2 Up
|
||||
["r"] = 107, -- 1/4 Cir Up 2 For
|
||||
["s"] = 108, -- 1/4 Cir Back 2 Down
|
||||
["t"] = 109, -- 1/4 Cir Down 2 For
|
||||
["u"] = 110, -- 1/4 Cir For 2 Up
|
||||
["v"] = 111, -- 1/4 Cir Up 2 Back
|
||||
["w"] = 112, -- Full Clock Forward
|
||||
["x"] = 113, -- Full Clock Back
|
||||
["y"] = 114, -- Full Count Forward
|
||||
["z"] = 115, -- Full Count Back
|
||||
["L"] = 116, -- 2x Forward
|
||||
["M"] = 117, -- 2x Back
|
||||
["Q"] = 118, -- Dragon Screw Forward
|
||||
["R"] = 119, -- Dragon Screw Back
|
||||
-- Big letter Text
|
||||
["^"] = 121, -- AIR
|
||||
["?"] = 122, -- DIR
|
||||
["X"] = 124, -- TAP
|
||||
-- Condition of Positions
|
||||
["|"] = 125, -- Jump
|
||||
["O"] = 126, -- Hold
|
||||
["-"] = 127, -- Air
|
||||
["="] = 128, -- Squatting
|
||||
["~"] = 131, -- Charge
|
||||
-- Special Character Text
|
||||
["`"] = 135, -- Small Dot
|
||||
["@"] = 136, -- Double Ball
|
||||
[")"] = 137, -- Single Ball
|
||||
["("] = 138, -- Solid Ball
|
||||
["*"] = 139, -- Star
|
||||
["&"] = 140, -- Solid star
|
||||
["%"] = 141, -- Triangle
|
||||
["$"] = 142, -- Solid Triangle
|
||||
["#"] = 143, -- Double Square
|
||||
["]"] = 144, -- Single Square
|
||||
["["] = 145, -- Solid Square
|
||||
["{"] = 146, -- Down Triangle
|
||||
["}"] = 147, -- Solid Down Triangle
|
||||
["<"] = 148, -- Diamond
|
||||
[">"] = 149, -- Solid Diamond
|
||||
}
|
||||
|
||||
local expand_text =
|
||||
{
|
||||
-- Alphabetic Buttons (NeoGeo): S (Slash Button)
|
||||
["s"] = 19, -- BTN_S
|
||||
-- Special Buttons
|
||||
["S"] = 52, -- BTN_SELECT
|
||||
-- Multiple Punches & Kicks
|
||||
["E"] = 57, -- Light Punch
|
||||
["F"] = 58, -- Middle Punch
|
||||
["G"] = 59, -- Strong Punch
|
||||
["H"] = 60, -- Light Kick
|
||||
["I"] = 61, -- Middle Kick
|
||||
["J"] = 62, -- Strong Kick
|
||||
["T"] = 63, -- 3 Kick
|
||||
["U"] = 64, -- 3 Punch
|
||||
["V"] = 65, -- 2 Kick
|
||||
["W"] = 66, -- 2 Pick
|
||||
-- Composition of Arrow Directions
|
||||
["!"] = 91, -- Continue Arrow
|
||||
-- Charge of Arrow Directions
|
||||
["1"] = 92, -- Charge DIR_1
|
||||
["2"] = 93, -- Charge DIR_2
|
||||
["3"] = 94, -- Charge DIR_3
|
||||
["4"] = 95, -- Charge DIR_4
|
||||
["6"] = 96, -- Charge DIR_6
|
||||
["7"] = 97, -- Charge DIR_7
|
||||
["8"] = 98, -- Charge DIR_8
|
||||
["9"] = 99, -- Charge DIR_9
|
||||
-- Big letter Text
|
||||
["M"] = 123, -- MAX
|
||||
-- Condition of Positions
|
||||
["-"] = 129, -- Close
|
||||
["="] = 130, -- Away
|
||||
["*"] = 132, -- Serious Tap
|
||||
["?"] = 133, -- Any Button
|
||||
}
|
||||
|
||||
local convert_text =
|
||||
{
|
||||
-- Alphabetic Buttons: A~Z
|
||||
["A-button"] = 1, -- BTN_A
|
||||
["B-button"] = 2, -- BTN_B
|
||||
["C-button"] = 3, -- BTN_C
|
||||
["D-button"] = 4, -- BTN_D
|
||||
["E-button"] = 5, -- BTN_E
|
||||
["F-button"] = 6, -- BTN_F
|
||||
["G-button"] = 7, -- BTN_G
|
||||
["H-button"] = 8, -- BTN_H
|
||||
["I-button"] = 9, -- BTN_I
|
||||
["J-button"] = 10, -- BTN_J
|
||||
["K-button"] = 11, -- BTN_K
|
||||
["L-button"] = 12, -- BTN_L
|
||||
["M-button"] = 13, -- BTN_M
|
||||
["N-button"] = 14, -- BTN_N
|
||||
["O-button"] = 15, -- BTN_O
|
||||
["P-button"] = 16, -- BTN_P
|
||||
["Q-button"] = 17, -- BTN_Q
|
||||
["R-button"] = 18, -- BTN_R
|
||||
["S-button"] = 19, -- BTN_S
|
||||
["T-button"] = 20, -- BTN_T
|
||||
["U-button"] = 21, -- BTN_U
|
||||
["V-button"] = 22, -- BTN_V
|
||||
["W-button"] = 23, -- BTN_W
|
||||
["X-button"] = 24, -- BTN_X
|
||||
["Y-button"] = 25, -- BTN_Y
|
||||
["Z-button"] = 26, -- BTN_Z
|
||||
-- Special Moves and Buttons
|
||||
["decrease"] = 37, -- BTN_DEC
|
||||
["increase"] = 38, -- BTN_INC
|
||||
["BALL"] = 45, -- Joystick Ball
|
||||
["start"] = 51, -- BTN_START
|
||||
["select"] = 52, -- BTN_SELECT
|
||||
["punch"] = 53, -- BTN_PUNCH
|
||||
["kick"] = 54, -- BTN_KICK
|
||||
["guard"] = 55, -- BTN_GUARD
|
||||
["L-punch"] = 57, -- Light Punch
|
||||
["M-punch"] = 58, -- Middle Punch
|
||||
["S-punch"] = 59, -- Strong Punch
|
||||
["L-kick"] = 60, -- Light Kick
|
||||
["M-kick"] = 61, -- Middle Kick
|
||||
["S-kick"] = 62, -- Strong Kick
|
||||
["3-kick"] = 63, -- 3 Kick
|
||||
["3-punch"] = 64, -- 3 Punch
|
||||
["2-kick"] = 65, -- 2 Kick
|
||||
["2-punch"] = 66, -- 2 Pick
|
||||
-- Custom Buttons and Cursor Buttons
|
||||
["custom1"] = 67, -- CUSTOM_1
|
||||
["custom2"] = 68, -- CUSTOM_2
|
||||
["custom3"] = 69, -- CUSTOM_3
|
||||
["custom4"] = 70, -- CUSTOM_4
|
||||
["custom5"] = 71, -- CUSTOM_5
|
||||
["custom6"] = 72, -- CUSTOM_6
|
||||
["custom7"] = 73, -- CUSTOM_7
|
||||
["custom8"] = 74, -- CUSTOM_8
|
||||
["up"] = 75, -- (Cursor Up)
|
||||
["down"] = 76, -- (Cursor Down)
|
||||
["left"] = 77, -- (Cursor Left)
|
||||
["right"] = 78, -- (Cursor Right)
|
||||
-- Player Lever
|
||||
["lever"] = 79, -- Non Player Lever
|
||||
["nplayer"] = 80, -- Gray Color Lever
|
||||
["1player"] = 81, -- 1 Player Lever
|
||||
["2player"] = 82, -- 2 Player Lever
|
||||
["3player"] = 83, -- 3 Player Lever
|
||||
["4player"] = 84, -- 4 Player Lever
|
||||
["5player"] = 85, -- 5 Player Lever
|
||||
["6player"] = 86, -- 6 Player Lever
|
||||
["7player"] = 87, -- 7 Player Lever
|
||||
["8player"] = 88, -- 8 Player Lever
|
||||
-- Composition of Arrow Directions
|
||||
["-->"] = 90, -- Arrow
|
||||
["==>"] = 91, -- Continue Arrow
|
||||
["hcb"] = 100, -- Half Circle Back
|
||||
["huf"] = 101, -- Half Circle Front Up
|
||||
["hcf"] = 102, -- Half Circle Front
|
||||
["hub"] = 103, -- Half Circle Back Up
|
||||
["qfd"] = 104, -- 1/4 Cir For 2 Down
|
||||
["qdb"] = 105, -- 1/4 Cir Down 2 Back
|
||||
["qbu"] = 106, -- 1/4 Cir Back 2 Up
|
||||
["quf"] = 107, -- 1/4 Cir Up 2 For
|
||||
["qbd"] = 108, -- 1/4 Cir Back 2 Down
|
||||
["qdf"] = 109, -- 1/4 Cir Down 2 For
|
||||
["qfu"] = 110, -- 1/4 Cir For 2 Up
|
||||
["qub"] = 111, -- 1/4 Cir Up 2 Back
|
||||
["fdf"] = 112, -- Full Clock Forward
|
||||
["fub"] = 113, -- Full Clock Back
|
||||
["fuf"] = 114, -- Full Count Forward
|
||||
["fdb"] = 115, -- Full Count Back
|
||||
["xff"] = 116, -- 2x Forward
|
||||
["xbb"] = 117, -- 2x Back
|
||||
["dsf"] = 118, -- Dragon Screw Forward
|
||||
["dsb"] = 119, -- Dragon Screw Back
|
||||
-- Big letter Text
|
||||
["AIR"] = 121, -- AIR
|
||||
["DIR"] = 122, -- DIR
|
||||
["MAX"] = 123, -- MAX
|
||||
["TAP"] = 124, -- TAP
|
||||
-- Condition of Positions
|
||||
["jump"] = 125, -- Jump
|
||||
["hold"] = 126, -- Hold
|
||||
["air"] = 127, -- Air
|
||||
["sit"] = 128, -- Squatting
|
||||
["close"] = 129, -- Close
|
||||
["away"] = 130, -- Away
|
||||
["charge"] = 131, -- Charge
|
||||
["tap"] = 132, -- Serious Tap
|
||||
["button"] = 133, -- Any Button
|
||||
}
|
||||
|
||||
local function convert_char(str)
|
||||
str = str:gsub("@(%g+)", function(s) if convert_text[s] then return utf8.char(convert_text[s] + 0xe000) end return s end)
|
||||
str = str:gsub("_(%g)", function(s) if default_text[s] then return utf8.char(default_text[s] + 0xe000) end return s end)
|
||||
str = str:gsub("%^(%g)", function(s) if expand_text[s] then return utf8.char(expand_text[s] + 0xe000) end return s end)
|
||||
return str
|
||||
end
|
||||
|
||||
return convert_char
|
||||
36
bios/Arcade/MAME/plugins/data/data_command.lua
Normal file
36
bios/Arcade/MAME/plugins/data/data_command.lua
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
local dat = {}
|
||||
|
||||
local info, ver
|
||||
local datread = require('data/load_dat')
|
||||
do
|
||||
local buttonchar
|
||||
local function convert(str)
|
||||
if not buttonchar then
|
||||
buttonchar = require("data/button_char")
|
||||
end
|
||||
return buttonchar(str)
|
||||
end
|
||||
datread, ver = datread.open('command.dat', '#[^V]*Ver[^.:]*[.:]', convert)
|
||||
end
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, info = pcall(datread, 'cmd', 'info', set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
return _p('plugin-data', 'Command')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
27
bios/Arcade/MAME/plugins/data/data_gameinit.lua
Normal file
27
bios/Arcade/MAME/plugins/data/data_gameinit.lua
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
local dat = {}
|
||||
|
||||
local ver, info
|
||||
local datread = require('data/load_dat')
|
||||
datread, ver = datread.open('gameinit.dat', '# .-GAMEINIT.DAT')
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, info = pcall(datread, 'mame', 'info', set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
return _p('plugin-data', 'Gameinit')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
1278
bios/Arcade/MAME/plugins/data/data_hiscore.lua
Normal file
1278
bios/Arcade/MAME/plugins/data/data_hiscore.lua
Normal file
File diff suppressed because it is too large
Load diff
218
bios/Arcade/MAME/plugins/data/data_history.lua
Normal file
218
bios/Arcade/MAME/plugins/data/data_history.lua
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
local dat = {}
|
||||
|
||||
local db = require('data/database')
|
||||
local ver, info
|
||||
local file = 'history.xml'
|
||||
local tablename
|
||||
|
||||
local function init()
|
||||
-- check for old history table
|
||||
if db.get_version('history.dat') then
|
||||
db.exec([[DROP TABLE "history.dat";]])
|
||||
db.exec([[DROP TABLE "history.dat_idx";]])
|
||||
db.set_version('history.dat', nil)
|
||||
end
|
||||
|
||||
local fh, filepath, dbver
|
||||
fh, filepath, tablename, dbver = db.open_data_file(file)
|
||||
if not fh then
|
||||
if dbver then
|
||||
-- data in database but missing file, just use what we have
|
||||
ver = dbver
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- scan file for version
|
||||
for line in fh:lines() do
|
||||
local match = line:match('<history([^>]*)>')
|
||||
if match then
|
||||
match = match:match('version="([^"]*)"')
|
||||
if match then
|
||||
ver = match
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if (not ver) or (ver == dbver) then
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
if not dbver then
|
||||
db.exec(
|
||||
string.format(
|
||||
[[CREATE TABLE "%s_idx" (
|
||||
name VARCHAR NOT NULL,
|
||||
list VARCHAR NOT NULL,
|
||||
data INTEGER NOT NULL);]],
|
||||
tablename))
|
||||
db.check(string.format('creating %s index table', file))
|
||||
db.exec(string.format([[CREATE TABLE "%s" (data CLOB NOT NULL);]], tablename))
|
||||
db.check(string.format('creating %s data table', file))
|
||||
db.exec(
|
||||
string.format(
|
||||
[[CREATE INDEX "namelist_%s" ON "%s_idx" (name, list);]],
|
||||
tablename, tablename))
|
||||
db.check(string.format('creating %s name/list index', file))
|
||||
end
|
||||
|
||||
local slaxml = require('xml')
|
||||
|
||||
db.exec([[BEGIN TRANSACTION;]])
|
||||
if not db.check(string.format('starting %s transaction', file)) then
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
-- clean out previous data and update the version
|
||||
if dbver then
|
||||
db.exec(string.format([[DELETE FROM "%s";]], tablename))
|
||||
if not db.check(string.format('deleting previous %s data', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
db.exec(string.format([[DELETE FROM "%s_idx";]], tablename))
|
||||
if not db.check(string.format('deleting previous %s data', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
end
|
||||
db.set_version(file, ver)
|
||||
if not db.check(string.format('updating %s version', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
fh:seek('set')
|
||||
local buffer = fh:read('a')
|
||||
|
||||
local lasttag
|
||||
local entry = {}
|
||||
local rowid
|
||||
|
||||
local dataquery = db.prepare(
|
||||
string.format([[INSERT INTO "%s" (data) VALUES (?);]], tablename))
|
||||
local indexquery = db.prepare(
|
||||
string.format([[INSERT INTO "%s_idx" (name, list, data) VALUES (?, ?, ?);]], tablename))
|
||||
|
||||
local parser = slaxml:parser{
|
||||
startElement = function(name)
|
||||
lasttag = name
|
||||
if name == 'entry' then
|
||||
entry = {}
|
||||
rowid = nil
|
||||
elseif (name == 'system') or (name == 'item') then
|
||||
table.insert(entry, {})
|
||||
end
|
||||
end,
|
||||
attribute = function(name, value)
|
||||
if (name == 'name') or (name == 'list') then
|
||||
entry[#entry][name] = value
|
||||
end
|
||||
end,
|
||||
text = function(text, cdata)
|
||||
if lasttag == 'text' then
|
||||
text = text:gsub('\r', '') -- strip carriage returns
|
||||
dataquery:bind_values(text)
|
||||
while true do
|
||||
local status = dataquery:step()
|
||||
if status == db.DONE then
|
||||
rowid = dataquery:last_insert_rowid();
|
||||
break
|
||||
elseif result == db.BUSY then
|
||||
emu.print_error(string.format('Database busy: inserting %s data', file))
|
||||
-- FIXME: how to abort parse and roll back?
|
||||
break
|
||||
elseif result ~= db.ROW then
|
||||
db.check(string.format('inserting %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
dataquery:reset()
|
||||
end
|
||||
end,
|
||||
closeElement = function(name)
|
||||
if (name == 'entry') and rowid then
|
||||
for num, entry in pairs(entry) do
|
||||
indexquery:bind_values(entry.name, entry.list or '', rowid)
|
||||
while true do
|
||||
local status = indexquery:step()
|
||||
if status == db.DONE then
|
||||
break
|
||||
elseif status == db.BUSY then
|
||||
emu.print_error(string.format('Database busy: inserting %s data', file))
|
||||
-- FIXME: how to abort parse and roll back?
|
||||
break
|
||||
elseif result ~= db.ROW then
|
||||
db.check(string.format('inserting %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
indexquery:reset()
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
parser:parse(buffer, { stripWhitespace = true })
|
||||
dataquery:finalize()
|
||||
indexquery:finalize()
|
||||
fh:close()
|
||||
|
||||
db.exec([[COMMIT TRANSACTION;]])
|
||||
if not db.check(string.format('committing %s transaction', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
ver = dbver
|
||||
end
|
||||
end
|
||||
|
||||
if db then
|
||||
init()
|
||||
end
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if not ver then
|
||||
return nil
|
||||
end
|
||||
|
||||
info = nil
|
||||
local query = db.prepare(
|
||||
string.format(
|
||||
[[SELECT f.data
|
||||
FROM "%s_idx" AS fi LEFT JOIN "%s" AS f ON fi.data = f.rowid
|
||||
WHERE fi.name = ? AND fi.list = ?;]],
|
||||
tablename, tablename))
|
||||
query:bind_values(set, softlist or '')
|
||||
while not info do
|
||||
local status = query:step()
|
||||
if status == db.ROW then
|
||||
info = query:get_value(0)
|
||||
elseif status == db.DONE then
|
||||
break
|
||||
elseif status ~= db.BUSY then
|
||||
db.check(string.format('reading %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
query:finalize()
|
||||
return info and _p('plugin-data', 'History') or nil
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
38
bios/Arcade/MAME/plugins/data/data_mameinfo.lua
Normal file
38
bios/Arcade/MAME/plugins/data/data_mameinfo.lua
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
local dat = {}
|
||||
|
||||
local info, ver
|
||||
local datread = require('data/load_dat')
|
||||
datread, ver = datread.open(
|
||||
'mameinfo.dat',
|
||||
'# MAMEINFO.DAT',
|
||||
function (str) return str:gsub('\n\n', '\n') end)
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status, drvinfo
|
||||
status, info = pcall(datread, 'mame', 'info', set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
local sourcefile = emu.driver_find(set).source_file:match('[^/\\]+[/\\\\][^/\\]*$')
|
||||
status, drvinfo = pcall(datread, 'drv', 'info', sourcefile)
|
||||
if not drvinfo then
|
||||
status, drvinfo = pcall(datread, 'drv', 'info', sourcefile:match('[^/\\]*$'))
|
||||
end
|
||||
if drvinfo then
|
||||
info = info .. _p('plugin-data', '\n\n--- DRIVER INFO ---\nDriver: ') .. sourcefile .. '\n\n' .. drvinfo
|
||||
end
|
||||
return _p('plugin-data', 'MAMEinfo')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
179
bios/Arcade/MAME/plugins/data/data_marp.lua
Normal file
179
bios/Arcade/MAME/plugins/data/data_marp.lua
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
-- get marp high score file from http://replay.marpirc.net/txt/scores3.htm
|
||||
local dat = {}
|
||||
|
||||
local db = require("data/database")
|
||||
local ver, info
|
||||
|
||||
local function init()
|
||||
local file = 'scores3.htm'
|
||||
|
||||
local fh, filepath, tablename, dbver = db.open_data_file(file)
|
||||
if not fh then
|
||||
if dbver then
|
||||
-- data in database but missing file, just use what we have
|
||||
ver = dbver
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- scan file for version
|
||||
for line in fh:lines() do
|
||||
local match = line:match('Top Scores from the MAME Action Replay Page %(([%w :]+)%)')
|
||||
if match then
|
||||
ver = match
|
||||
break
|
||||
end
|
||||
end
|
||||
if (not ver) or (ver == dbver) then
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
if not dbver then
|
||||
db.exec(
|
||||
string.format(
|
||||
[[CREATE TABLE "%s" (
|
||||
romset VARCHAR NOT NULL,
|
||||
data CLOB NOT NULL,
|
||||
PRIMARY KEY(romset));]],
|
||||
tablename))
|
||||
db.check('creating MARP table')
|
||||
end
|
||||
|
||||
db.exec([[BEGIN TRANSACTION;]])
|
||||
if not db.check('starting MARP transaction') then
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
-- clean out previous data and update the version
|
||||
if dbver then
|
||||
db.exec(string.format([[DELETE FROM "%s";]], tablename))
|
||||
if not db.check('deleting previous MARP data') then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
end
|
||||
if not db.set_version(file, ver) then
|
||||
db.check('updating MARP version')
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
end
|
||||
|
||||
fh:seek('set')
|
||||
local buffer = fh:read('a')
|
||||
|
||||
local function gmatchpos()
|
||||
local pos = 1
|
||||
local set = ''
|
||||
local data = ''
|
||||
local function iter()
|
||||
local lastset = set
|
||||
while true do
|
||||
local spos, scr, plyr, stype, ltype
|
||||
spos, pos, set, stype, scr, plyr, ltype = buffer:find('\n%s*([%w_]*)%-?(%w-) :%s*(%d+) [;:] ([^:]+): [^%[\n]*%[?([%w ]*)[^\n]*', pos)
|
||||
if not spos then
|
||||
return nil
|
||||
end
|
||||
|
||||
local url = ''
|
||||
if set ~= '' then
|
||||
if ltype ~= '' then
|
||||
url = ltype .. '\t\n'
|
||||
end
|
||||
url = url .. 'http://replay.marpirc.net/r/' .. set
|
||||
if stype ~= '' then
|
||||
url = url .. '-' .. stype
|
||||
end
|
||||
url = url .. '\t\n'
|
||||
end
|
||||
|
||||
if (set ~= '') and (lastset ~= set) then
|
||||
local lastdata = data
|
||||
data = url .. plyr .. '\t' .. scr .. '\n'
|
||||
return lastset, lastdata
|
||||
end
|
||||
|
||||
if url ~= '' then
|
||||
data = data .. '\n' .. url
|
||||
end
|
||||
data = data .. plyr .. '\t' .. scr .. '\n'
|
||||
end
|
||||
end
|
||||
return iter
|
||||
end
|
||||
|
||||
local query = db.prepare(
|
||||
string.format([[INSERT INTO "%s" (romset, data) VALUES (?, ?)]], tablename))
|
||||
for set, data in gmatchpos() do
|
||||
query:bind_values(set, data)
|
||||
while true do
|
||||
local status = query:step()
|
||||
if status == db.DONE then
|
||||
break
|
||||
elseif status == db.BUSY then
|
||||
emu.print_error('Database busy: inserting MARP data')
|
||||
query:finalize()
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
ver = dbver
|
||||
return
|
||||
elseif result ~= db.ROW then
|
||||
db.check('inserting MARP data')
|
||||
break
|
||||
end
|
||||
end
|
||||
query:reset()
|
||||
end
|
||||
query:finalize()
|
||||
|
||||
fh:close()
|
||||
db.exec([[COMMIT TRANSACTION;]])
|
||||
if not db.check('committing MARP transaction') then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
ver = dbver
|
||||
end
|
||||
end
|
||||
|
||||
if db then
|
||||
init()
|
||||
end
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or (not ver) then
|
||||
return nil
|
||||
end
|
||||
|
||||
info = nil
|
||||
local query = db.prepare([[SELECT data FROM "scores3.htm" WHERE romset = ?;]])
|
||||
query:bind_values(set)
|
||||
while not info do
|
||||
local status = query:step()
|
||||
if status == db.ROW then
|
||||
info = '#j2\n' .. query:get_value(0)
|
||||
elseif status == db.DONE then
|
||||
break
|
||||
elseif status ~= db.BUSY then
|
||||
db.check('reading MARP data')
|
||||
break
|
||||
end
|
||||
end
|
||||
query:finalize()
|
||||
return info and _p('plugin-data', 'MARPScore') or nil
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
38
bios/Arcade/MAME/plugins/data/data_messinfo.lua
Normal file
38
bios/Arcade/MAME/plugins/data/data_messinfo.lua
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
local dat = {}
|
||||
|
||||
local ver, info
|
||||
local datread = require('data/load_dat')
|
||||
datread, ver = datread.open(
|
||||
'messinfo.dat',
|
||||
'# MESSINFO.DAT',
|
||||
function (str) return str:gsub('\n\n', '\n') end)
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status, drvinfo
|
||||
status, info = pcall(datread, 'mame', 'info', set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
local sourcefile = emu.driver_find(set).source_file:match('[^/\\]+[/\\\\][^/\\]*$')
|
||||
status, drvinfo = pcall(datread, 'drv', 'info', sourcefile)
|
||||
if not drvinfo then
|
||||
status, drvinfo = pcall(datread, 'drv', 'info', sourcefile:match('[^/\\]*$'))
|
||||
end
|
||||
if drvinfo then
|
||||
info = info .. _p('plugin-data', '\n\n--- DRIVER INFO ---\nDriver: ') .. sourcefile .. '\n\n' .. drvinfo
|
||||
end
|
||||
return _p('plugin-data', 'MESSinfo')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
35
bios/Arcade/MAME/plugins/data/data_story.lua
Normal file
35
bios/Arcade/MAME/plugins/data/data_story.lua
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
local dat = {}
|
||||
|
||||
local ver, info
|
||||
local datread = require('data/load_dat')
|
||||
datread, ver = datread.open('story.dat', '# version')
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status, data = pcall(datread, 'story', 'info', set)
|
||||
if not status or not data then
|
||||
return nil
|
||||
end
|
||||
local lines = {}
|
||||
data = data:gsub('MAMESCORE records : ([^\n]+)', 'MAMESCORE records :\t\n%1', 1)
|
||||
for line in data:gmatch('[^\n]*') do
|
||||
if (line ~= '') or ((#lines ~= 0) and (lines[#lines] ~= '')) then
|
||||
line = line:gsub('^(.-)_+([0-9.]+)$', '%1\t%2')
|
||||
table.insert(lines, line)
|
||||
end
|
||||
end
|
||||
info = '#j2\n' .. table.concat(lines, '\n')
|
||||
return _p('plugin-data', 'Mamescore')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
27
bios/Arcade/MAME/plugins/data/data_sysinfo.lua
Normal file
27
bios/Arcade/MAME/plugins/data/data_sysinfo.lua
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
local dat = {}
|
||||
|
||||
local ver, info
|
||||
local datread = require('data/load_dat')
|
||||
datread, ver = datread.open('sysinfo.dat', '# This file was generated on')
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, info = pcall(datread, 'bio', 'info', set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
return _p('plugin-data', 'Sysinfo')
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
function dat.ver()
|
||||
return ver
|
||||
end
|
||||
|
||||
return dat
|
||||
159
bios/Arcade/MAME/plugins/data/database.lua
Normal file
159
bios/Arcade/MAME/plugins/data/database.lua
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
local sql = require('lsqlite3')
|
||||
local db
|
||||
|
||||
local function check_db_result(msg)
|
||||
if db:errcode() > sql.OK then
|
||||
emu.print_error(string.format('Error: %s (%s - %s)', msg, db:errcode(), db:errmsg()))
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function settings_path()
|
||||
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/data'
|
||||
end
|
||||
|
||||
local function check_version_table()
|
||||
local found = false
|
||||
db:exec(
|
||||
[[SELECT COUNT(*) FROM sqlite_master WHERE name = 'version' AND type = 'table';]],
|
||||
function (udata, cols, values, names)
|
||||
found = tonumber(values[1]) > 0
|
||||
return 0
|
||||
end)
|
||||
if check_db_result('checking for "version" table') and (not found) then
|
||||
db:exec(
|
||||
[[CREATE TABLE version (
|
||||
datfile VARCHAR NOT NULL,
|
||||
version VARCHAR NOT NULL,
|
||||
PRIMARY KEY (datfile));]])
|
||||
found = check_db_result('creating "version" table')
|
||||
end
|
||||
if not found then
|
||||
db:close()
|
||||
db = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function open_existing()
|
||||
db = sql.open(settings_path() .. '/history.db', sql.OPEN_READWRITE)
|
||||
if db then
|
||||
check_version_table()
|
||||
end
|
||||
return db
|
||||
end
|
||||
|
||||
local function open_create()
|
||||
-- first try to create settings directory
|
||||
local dir = settings_path()
|
||||
local attr = lfs.attributes(dir)
|
||||
if (not attr) and (not lfs.mkdir(dir)) then
|
||||
emu.print_error(string.format('Error creating data plugin settings directory "%s"', dir))
|
||||
elseif attr and (attr.mode ~= 'directory') then
|
||||
emu.print_error(string.format('Error opening data plugin database: "%s" is not a directory', dir))
|
||||
else
|
||||
-- now try to open the database
|
||||
local dbpath = dir .. '/history.db'
|
||||
db = sql.open(dbpath, sql.OPEN_READWRITE | sql.OPEN_CREATE)
|
||||
if not db then
|
||||
emu.print_error(string.format('Error opening data plugin database "%s"', dbpath))
|
||||
else
|
||||
check_version_table()
|
||||
end
|
||||
end
|
||||
return db
|
||||
end
|
||||
|
||||
|
||||
local dbtable = {
|
||||
ROW = sql.ROW,
|
||||
BUSY = sql.BUSY,
|
||||
DONE = sql.DONE,
|
||||
check = check_db_result }
|
||||
|
||||
function dbtable.sanitize_name(name)
|
||||
return name:gsub('[^%w%."]', '_')
|
||||
end
|
||||
|
||||
function dbtable.get_version(filename)
|
||||
-- don't try to create the database here, just return nil if it doesn't exist
|
||||
if (not db) and (not open_existing()) then
|
||||
return nil
|
||||
end
|
||||
local query = db:prepare([[SELECT version FROM version WHERE datfile = ?;]])
|
||||
query:bind_values(filename)
|
||||
local result
|
||||
while result == nil do
|
||||
local status = query:step()
|
||||
if status == sql.ROW then
|
||||
result = query:get_value(0)
|
||||
elseif status ~= sql.BUSY then
|
||||
break
|
||||
end
|
||||
end
|
||||
query:finalize()
|
||||
return result
|
||||
end
|
||||
|
||||
function dbtable.set_version(filename, version)
|
||||
if (not db) and (not open_create()) then
|
||||
return nil
|
||||
end
|
||||
local query
|
||||
if version ~= nil then
|
||||
query = db:prepare(
|
||||
[[INSERT INTO version (datfile, version) VALUES (?1, ?2)
|
||||
ON CONFLICT(datfile) DO UPDATE set version = ?2;]])
|
||||
query:bind_values(filename, version)
|
||||
else
|
||||
query = db:prepare([[DELETE FROM version WHERE datfile = ?1;]])
|
||||
query:bind_values(filename)
|
||||
end
|
||||
local result
|
||||
while result == nil do
|
||||
local status = query:step()
|
||||
if status == sql.DONE then
|
||||
result = true
|
||||
elseif result ~= sql.ROW then
|
||||
result = false
|
||||
end
|
||||
end
|
||||
query:finalize()
|
||||
return result
|
||||
end
|
||||
|
||||
function dbtable.prepare(...)
|
||||
if (not db) and open_create() then
|
||||
dbtable.prepare = function (...) return db:prepare(...) end
|
||||
end
|
||||
if db then
|
||||
return db:prepare(...)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dbtable.exec(...)
|
||||
if (not db) and open_create() then
|
||||
dbtable.exec = function (...) return db:exec(...) end
|
||||
end
|
||||
if db then
|
||||
return db:exec(...)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dbtable.open_data_file(file)
|
||||
local fh, filepath
|
||||
for path in mame_manager.ui.options.entries.historypath:value():gmatch('([^;]+)') do
|
||||
filepath = path .. '/' .. file
|
||||
fh = io.open(filepath, 'r')
|
||||
if fh then
|
||||
break
|
||||
end
|
||||
end
|
||||
return fh, filepath, dbtable.sanitize_name(file), dbtable.get_version(file)
|
||||
end
|
||||
|
||||
return dbtable
|
||||
91
bios/Arcade/MAME/plugins/data/init.lua
Normal file
91
bios/Arcade/MAME/plugins/data/init.lua
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
-- license:BSD-3-Clause
|
||||
-- copyright-holders:Carl
|
||||
-- A data script should contain two functions check which takes a set name and returns the data
|
||||
-- heading if it supports the set otherwise nil and get which returns the data
|
||||
-- the script should be named data_<name>.lua
|
||||
-- this is set default on in the plugin.json
|
||||
local exports = {
|
||||
name = 'data',
|
||||
version = '0.0.2',
|
||||
description = 'Data plugin',
|
||||
license = 'BSD-3-Clause',
|
||||
author = { name = 'Carl' } }
|
||||
|
||||
local data = exports
|
||||
|
||||
local plugindir
|
||||
|
||||
local reset_subscription
|
||||
|
||||
function data.set_folder(path)
|
||||
plugindir = path
|
||||
end
|
||||
|
||||
function data.startplugin()
|
||||
local data_scr = {}
|
||||
local valid_lst = {}
|
||||
local cur_set
|
||||
local cur_list
|
||||
|
||||
reset_subscription = emu.add_machine_reset_notifier(
|
||||
function ()
|
||||
data_scr = {}
|
||||
for file in lfs.dir(plugindir) do
|
||||
local name = string.match(file, '^(data_.*).lua$')
|
||||
if name then
|
||||
local script = require('data/' .. name)
|
||||
if script then
|
||||
table.insert(data_scr, script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
emu.register_callback(
|
||||
function (set)
|
||||
local ret = {}
|
||||
if set == '' then
|
||||
set = emu.romname()
|
||||
end
|
||||
if set == cur_set then
|
||||
return cur_list
|
||||
end
|
||||
cur_set = set
|
||||
if not set then
|
||||
return nil
|
||||
end
|
||||
valid_lst = {}
|
||||
for num, scr in ipairs(data_scr) do
|
||||
local setname, softname = set:match('^([^,]+),?(.*)$')
|
||||
if softname == '' then
|
||||
softname = nil
|
||||
end
|
||||
local name = scr.check(setname, softname)
|
||||
if name then
|
||||
table.insert(ret, name)
|
||||
table.insert(valid_lst, scr)
|
||||
end
|
||||
end
|
||||
cur_list = ret
|
||||
return ret
|
||||
end,
|
||||
'data_list')
|
||||
|
||||
emu.register_callback(
|
||||
function (num)
|
||||
return valid_lst[num + 1].get()
|
||||
end,
|
||||
'data')
|
||||
|
||||
emu.register_callback(
|
||||
function (num)
|
||||
local ver
|
||||
if valid_lst[num + 1].ver then
|
||||
ver = valid_lst[num + 1].ver()
|
||||
end
|
||||
return ver or ''
|
||||
end,
|
||||
'data_version')
|
||||
end
|
||||
|
||||
return exports
|
||||
260
bios/Arcade/MAME/plugins/data/load_dat.lua
Normal file
260
bios/Arcade/MAME/plugins/data/load_dat.lua
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
local datfile = {}
|
||||
|
||||
local db = require('data/database')
|
||||
|
||||
local function readret(file, tablename)
|
||||
local query = db.prepare(
|
||||
string.format(
|
||||
[[SELECT f.data
|
||||
FROM "%s_idx" AS fi LEFT JOIN "%s" AS f ON fi.data = f.rowid
|
||||
WHERE fi.type = ? AND fi.val = ? AND fi.romset = ?;]],
|
||||
tablename, tablename))
|
||||
local function read(tag, val, set)
|
||||
query:bind_values(tag, val, set)
|
||||
local data
|
||||
while not data do
|
||||
local status = query:step()
|
||||
if status == db.ROW then
|
||||
data = query:get_value(0)
|
||||
elseif status == db.DONE then
|
||||
break
|
||||
elseif status ~= db.BUSY then
|
||||
db.check(string.format('reading %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
query:reset()
|
||||
return data
|
||||
end
|
||||
return read
|
||||
end
|
||||
|
||||
|
||||
function datfile.open(file, vertag, fixupcb)
|
||||
if not db then
|
||||
return nil
|
||||
end
|
||||
|
||||
local fh, filepath, tablename, dbver = db.open_data_file(file)
|
||||
if not fh then
|
||||
if dbver then
|
||||
-- data in database but missing file, just use what we have
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local ver
|
||||
if vertag then
|
||||
-- scan file for version
|
||||
for line in fh:lines() do
|
||||
local match = line:match(vertag .. '%s*(%S+)')
|
||||
if match then
|
||||
ver = match
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not ver then
|
||||
-- fall back to file modification time for version
|
||||
ver = tostring(lfs.attributes(filepath, 'change'))
|
||||
end
|
||||
if ver == dbver then
|
||||
fh:close()
|
||||
return readret(file, tablename), dbver
|
||||
end
|
||||
|
||||
if not dbver then
|
||||
db.exec(
|
||||
string.format(
|
||||
[[CREATE TABLE "%s_idx" (
|
||||
type VARCHAR NOT NULL,
|
||||
val VARCHAR NOT NULL,
|
||||
romset VARCHAR NOT NULL,
|
||||
data INTEGER NOT NULL);]],
|
||||
tablename))
|
||||
db.check(string.format('creating %s index table', file))
|
||||
db.exec(string.format([[CREATE TABLE "%s" (data CLOB NOT NULL);]], tablename))
|
||||
db.check(string.format('creating %s data table', file))
|
||||
db.exec(
|
||||
string.format(
|
||||
[[CREATE INDEX "typeval_%s" ON "%s_idx" (type, val, romset);]],
|
||||
tablename, tablename))
|
||||
db.check(string.format('creating %s type/value index', file))
|
||||
end
|
||||
|
||||
db.exec([[BEGIN TRANSACTION;]])
|
||||
if not db.check(string.format('starting %s transaction', file)) then
|
||||
fh:close()
|
||||
if dbver then
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- clean out previous data and update the version
|
||||
if dbver then
|
||||
db.exec(string.format([[DELETE FROM "%s";]], tablename))
|
||||
if not db.check(string.format('deleting previous %s data', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
return readret(file, tablename), dbver
|
||||
end
|
||||
db.exec(string.format([[DELETE FROM "%s_idx";]], tablename))
|
||||
if not db.check(string.format('deleting previous %s data', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
return readret(file, tablename), dbver
|
||||
end
|
||||
end
|
||||
db.set_version(file, ver)
|
||||
if not db.check(string.format('updating %s version', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
if dbver then
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local dataquery = db.prepare(
|
||||
string.format([[INSERT INTO "%s" (data) VALUES (?);]], tablename))
|
||||
local indexquery = db.prepare(
|
||||
string.format(
|
||||
[[INSERT INTO "%s_idx" (type, val, romset, data) VALUES (?, ?, ?, ?)]],
|
||||
tablename))
|
||||
|
||||
fh:seek('set')
|
||||
local buffer = fh:read('a')
|
||||
|
||||
local function gmatchpos()
|
||||
local pos = 1
|
||||
local function iter()
|
||||
local tags, data
|
||||
while not data do
|
||||
local npos
|
||||
local spos, epos = buffer:find('[\n\r]$[^=\n\r]*=[^\n\r]*', pos)
|
||||
if not spos then
|
||||
return nil
|
||||
end
|
||||
npos, epos = buffer:find('[\n\r]$%w+%s*[\n\r]+', epos)
|
||||
if not npos then
|
||||
return nil
|
||||
end
|
||||
tags = buffer:sub(spos, epos)
|
||||
spos, npos = buffer:find('[\n\r]$[^=\n\r]*=[^\n\r]*', epos)
|
||||
if not spos then
|
||||
return nil
|
||||
end
|
||||
data = buffer:sub(epos, spos)
|
||||
pos = spos
|
||||
end
|
||||
return tags, data
|
||||
end
|
||||
return iter
|
||||
end
|
||||
|
||||
for info, data in gmatchpos() do
|
||||
local tags = {}
|
||||
local infotype
|
||||
info = info:gsub(utf8.char(0xfeff), '') -- remove byte order marks
|
||||
data = data:gsub(utf8.char(0xfeff), '')
|
||||
for s in info:gmatch('[\n\r]$([^\n\r]*)') do
|
||||
if s:find('=', 1, true) then
|
||||
local m1, m2 = s:match('([^=]*)=(.*)')
|
||||
for tag in m1:gmatch('[^,]+') do
|
||||
for set in m2:gmatch('[^,]+') do
|
||||
table.insert(tags, { tag = tag, set = set })
|
||||
end
|
||||
end
|
||||
else
|
||||
infotype = s
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
data = data:gsub('[\n\r]$end%s*[\n\r]$%w+%s*[\n\r]', '\n')
|
||||
data = data:gsub('[\n\r]$end%s*[\n\r].-[\n\r]$%w+%s*[\n\r]', '\n')
|
||||
data = data:gsub('[\n\r]$end%s*[\n\r].*', '')
|
||||
|
||||
if (#tags > 0) and infotype then
|
||||
data = data:gsub('\r', '') -- strip carriage returns
|
||||
if fixupcb then
|
||||
data = fixupcb(data)
|
||||
end
|
||||
|
||||
dataquery:bind_values(data)
|
||||
local row
|
||||
while true do
|
||||
local status = dataquery:step()
|
||||
if status == db.DONE then
|
||||
row = dataquery:last_insert_rowid();
|
||||
break
|
||||
elseif status == db.BUSY then
|
||||
emu.print_error(string.format('Database busy: inserting %s data', file))
|
||||
dataquery:finalize()
|
||||
indexquery:finalize()
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
if dbver then
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
elseif result ~= db.ROW then
|
||||
db.check(string.format('inserting %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
dataquery:reset()
|
||||
|
||||
if row then
|
||||
for num, tag in pairs(tags) do
|
||||
indexquery:bind_values(infotype, tag.tag, tag.set, row)
|
||||
while true do
|
||||
local status = indexquery:step()
|
||||
if status == db.DONE then
|
||||
break
|
||||
elseif status == db.BUSY then
|
||||
emu.print_error(string.format('Database busy: inserting %s data', file))
|
||||
dataquery:finalize()
|
||||
indexquery:finalize()
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
fh:close()
|
||||
if dbver then
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
elseif result ~= db.ROW then
|
||||
db.check(string.format('inserting %s data', file))
|
||||
break
|
||||
end
|
||||
end
|
||||
indexquery:reset()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
dataquery:finalize()
|
||||
indexquery:finalize()
|
||||
|
||||
fh:close()
|
||||
db.exec([[COMMIT TRANSACTION;]])
|
||||
if not db.check(string.format('committing %s transaction', file)) then
|
||||
db.exec([[ROLLBACK TRANSACTION;]])
|
||||
if dbver then
|
||||
return readret(file, tablename), dbver
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
return readret(file, tablename), ver
|
||||
end
|
||||
|
||||
return datfile
|
||||
10
bios/Arcade/MAME/plugins/data/plugin.json
Normal file
10
bios/Arcade/MAME/plugins/data/plugin.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"plugin": {
|
||||
"name": "data",
|
||||
"description": "Data plugin",
|
||||
"version": "0.0.1",
|
||||
"author": "Carl",
|
||||
"type": "plugin",
|
||||
"start": "true"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue