mirror of
https://github.com/Abdess/retrobios.git
synced 2026-06-19 10:32: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
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue