mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
ui/selgame: get dat info from plugin [Carl]
plugins/data: add data plugin [Carl]
This commit is contained in:
parent
63ecb9a387
commit
46ab9213f5
245
plugins/data/button_char.lua
Normal file
245
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("@([a-zA-Z%-]+)", function(s) if convert_text[s] then return utf8.char(convert_text[s] + 0xe000) end return s end)
|
||||
str = str:gsub("_(.)", function(s) if default_text[s] then return utf8.char(default_text[s] + 0xe000) end return s end)
|
||||
str = str:gsub("%^(.)", function(s) if expand_text[s] then return utf8.char(expand_text[s] + 0xe000) end return s end)
|
||||
return str
|
||||
end
|
||||
|
||||
return convert_char
|
25
plugins/data/data_command.lua
Normal file
25
plugins/data/data_command.lua
Normal file
@ -0,0 +1,25 @@
|
||||
local dat = {}
|
||||
local info, ver
|
||||
|
||||
local datread = require("data/load_dat")
|
||||
datread, ver = datread.open("command.dat", nil)
|
||||
|
||||
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
|
||||
local convert = require("data/button_char")
|
||||
info = "#jf\n" .. convert(info)
|
||||
return "Command"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
23
plugins/data/data_gameinit.lua
Normal file
23
plugins/data/data_gameinit.lua
Normal file
@ -0,0 +1,23 @@
|
||||
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 "Gameinit"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
803
plugins/data/data_hiscore.lua
Normal file
803
plugins/data/data_hiscore.lua
Normal file
@ -0,0 +1,803 @@
|
||||
-- to use this get the package from http://greatstone.free.fr/hi2txt/
|
||||
-- extract the hi2txt.zip and place it in your history path
|
||||
|
||||
local dat = {}
|
||||
local env = {}
|
||||
local output
|
||||
local curset
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist then
|
||||
return nil
|
||||
end
|
||||
local datpath
|
||||
local function xml_parse()
|
||||
local file = emu.file(lfs.env_replace(mame_manager:ui():options().entries.historypath:value():gsub("([^;]+)", "%1/hi2txt")), 1)
|
||||
local ret = file:open(set .. ".xml")
|
||||
local table
|
||||
if ret then
|
||||
return nil
|
||||
end
|
||||
datpath = file:fullpath():gsub(".zip", "/")
|
||||
local data = file:read(file:size())
|
||||
data = data:match("<hi2txt>(.*)</ *hi2txt>")
|
||||
local function get_tags(str, parent)
|
||||
local arr = {}
|
||||
while str ~= "" do
|
||||
local tag, attr, stop
|
||||
tag, attr, stop, str = str:match("<([%w!_%-]+) ?(.-)(/?)[ %-]->(.*)")
|
||||
|
||||
if not tag then
|
||||
return arr
|
||||
end
|
||||
if tag:sub(0, 3) ~= "!--" then
|
||||
local block = {}
|
||||
if stop ~= "/" then
|
||||
local nest
|
||||
nest, str = str:match("(.-)</ *" .. tag .. " *>(.*)")
|
||||
local children = get_tags(nest, tag)
|
||||
if not next(children) then
|
||||
nest = nest:gsub("<!--.-%-%->", "")
|
||||
nest = nest:gsub("^%s*(.-)%s*$", "%1")
|
||||
block["text"] = nest
|
||||
else
|
||||
block = children
|
||||
end
|
||||
end
|
||||
if attr then
|
||||
for name, value in attr:gmatch("([-%w]-)=\"(.-)\"") do
|
||||
block[name] = value:gsub("^(.-)$", "%1")
|
||||
end
|
||||
end
|
||||
if not arr[tag] then
|
||||
arr[tag] = {}
|
||||
end
|
||||
if parent == "structure" or parent == "output" or parent == "format" or parent == "loop" or parent == "concat" then
|
||||
block["tag"] = tag
|
||||
arr[#arr + 1] = block
|
||||
elseif tag == "charset" or tag == "bitmask" then
|
||||
arr[tag][block["id"]] = block
|
||||
elseif tag == "case" or tag == "char" then
|
||||
arr[tag][block["src"]] = block
|
||||
else
|
||||
arr[tag][#arr[tag] + 1] = block
|
||||
end
|
||||
end
|
||||
end
|
||||
return arr
|
||||
end
|
||||
return get_tags(data, "")
|
||||
end
|
||||
|
||||
local function parse_table(xml)
|
||||
local total_size = 0
|
||||
local s = { "data = open('" .. xml.structure[1].file .. "', size)\noffset = 1\narr = {}" }
|
||||
local fparam = {}
|
||||
if xml.bitmask then
|
||||
local bitmask = "bitmask = {"
|
||||
for id, masks in pairs(xml.bitmask) do
|
||||
bitmask = bitmask .. "['" .. id .. "'] = {"
|
||||
for num, mask in ipairs(masks.character) do
|
||||
mask = mask:gsub("( )", "")
|
||||
local newmask = tonumber(mask, 2)
|
||||
local shift = 0
|
||||
local count = 8
|
||||
while (newmask & 1) == 0 do
|
||||
newmask = newmask >> 1
|
||||
shift = shift + 1
|
||||
end
|
||||
if masks.byte-completion and masks.byte-completion == "no" then
|
||||
count = 0
|
||||
while (newmask >> count) & 1 == 1 do
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
bitmask = bitmask .. "{ mask = " .. newmask .. ", ishift = " .. shift .. ", oshift = " .. count .. "},"
|
||||
end
|
||||
bitmask = bitmask .. "},"
|
||||
end
|
||||
s[#s + 1] = bitmask .. "}"
|
||||
end
|
||||
if xml.charset then
|
||||
local charset = "charset = {"
|
||||
for id, set in pairs(xml.charset) do
|
||||
local default
|
||||
charset = charset .. "['" .. id .. "'] = {"
|
||||
for src, char in pairs(set.char) do
|
||||
if char.default and char.default == "yes" then
|
||||
default = char.dst
|
||||
end
|
||||
charset = charset .. "[" .. src .. "]" .. " = '" .. char.dst .. "',"
|
||||
end
|
||||
if default then
|
||||
charset = charset .. "default = " .. default
|
||||
end
|
||||
charset = charset .. "},"
|
||||
end
|
||||
s[#s + 1] = charset .. "}"
|
||||
end
|
||||
|
||||
local function check_format(formstr)
|
||||
local formats = {}
|
||||
local ret = " function tempform(val)"
|
||||
formstr = formstr:gsub(">", ">")
|
||||
formstr:gsub("([^;]+)", function(s) formats[#formats + 1] = s end)
|
||||
for num, form in ipairs(formats) do
|
||||
local oper
|
||||
local first, rest = form:match("^(.)(.*)$")
|
||||
if first == "*" and tonumber(rest) then
|
||||
oper = " val = val * " .. rest
|
||||
elseif first == "/" and tonumber(rest) then
|
||||
oper = " val = val / " .. rest
|
||||
elseif first == "d" and tonumber(rest) then
|
||||
oper = " val = math.floor(val / " .. rest .. ")"
|
||||
elseif first == "D" and tonumber(rest) then
|
||||
oper = " val = math.floor((val / " .. rest .. ") + 0.5)"
|
||||
elseif first == "-" and tonumber(rest) then
|
||||
oper = " val = val - " .. rest
|
||||
elseif first == "+" and tonumber(rest) then
|
||||
oper = " val = val + " .. rest
|
||||
elseif first == "%" and tonumber(rest) then
|
||||
oper = " val = val % " .. rest
|
||||
elseif first == ">" and tonumber(rest) then
|
||||
oper = " val = val << " .. rest
|
||||
elseif first == "L" and (rest == "C" or rest == "owercase") then
|
||||
oper = " val = val:lower()"
|
||||
elseif first == "U" and (rest == "C" or rest == "ppercase") then
|
||||
oper = " val = val:upper()"
|
||||
elseif first == "C" and rest == "apitalize" then
|
||||
oper = " val = val:gsub('^(.)', function(s) return s:upper() end)"
|
||||
elseif first == "R" and (rest == "" or rest == "ound") then
|
||||
oper = " val = math.floor(" .. var .. " + 0.5)"
|
||||
elseif first == "T" then
|
||||
local trim, char = rest:match("rim(L?R?)(.)$")
|
||||
if trim == "L" or trim == "" then
|
||||
oper = " val = val:gsub('^(" .. char .. "*)', '')"
|
||||
end
|
||||
if trim == "R" or trim == "" then
|
||||
oper = " val = val:gsub('(" .. char .. "*)$', '')"
|
||||
end
|
||||
elseif first == "P" then
|
||||
local pad, count, char = rest:match("ad(L?R?)(%d-)(.)$")
|
||||
if pad == "L" then
|
||||
oper = " val = string.rep('" .. char .. "', " .. count .. " - #val) .. val"
|
||||
elseif pad == "R" then
|
||||
oper = "val = val .. string.rep('" .. char .. "', " .. count .. " - #val)"
|
||||
elseif pad == nil then
|
||||
local prefix = rest:match("refix(.*)")
|
||||
if prefix then
|
||||
oper = " val = '" .. rest .. "' .. val"
|
||||
end
|
||||
end
|
||||
elseif first == "S" then
|
||||
local suffix = rest:match("uffix(.*)")
|
||||
if suffix then
|
||||
oper = " val = val .. '" .. rest .. "'"
|
||||
end
|
||||
elseif (first == "h" and rest == "exadecimal_string") or (first == "0" and rest == "x") then
|
||||
oper = " val = string.format('0x%x', val)"
|
||||
elseif (first == "L" and rest == "oopIndex") then
|
||||
oper = " val = index"
|
||||
end
|
||||
if not oper then
|
||||
oper = " val = format['" .. form .. "'](val, {"
|
||||
for num1, colpar in ipairs(fparam[form]) do
|
||||
oper = oper .. "arr['" .. colpar .. "'][i].val or arr['" .. colpar .. "'][1].val,"
|
||||
end
|
||||
oper = oper .. "})"
|
||||
end
|
||||
ret = ret .. oper
|
||||
end
|
||||
return ret .. " return val\nend"
|
||||
end
|
||||
|
||||
if xml.format then
|
||||
local format = { "format = {" }
|
||||
for num, form in ipairs(xml.format) do
|
||||
local param = {}
|
||||
format[#format + 1] = "['" .. form["id"] .. "'] = "
|
||||
--[[if form["input-as-subcolumns-input"] then
|
||||
format[#format + 1] = "input_as_subcolumns_input = '" .. form["input-as-subcolumns-input"] .. "',"
|
||||
end]]--
|
||||
format[#format + 1] = "function(val, param) "
|
||||
if form["formatter"] then
|
||||
format[#format + 1] = "function tempform(val) "
|
||||
end
|
||||
if form["apply-to"] == "char" then
|
||||
format[#format + 1] = "val = val:gsub('(.)', function(val) "
|
||||
end
|
||||
format[#format + 1] = "local temp = val"
|
||||
for num1, op in ipairs(form) do
|
||||
if op.tag == "add" then
|
||||
format[#format + 1] = "val = val + " .. op.text
|
||||
elseif op.tag == "prefix" then
|
||||
format[#format + 1] = "val = '" .. op.text .. "' .. val "
|
||||
elseif op.tag == "suffix" then
|
||||
format[#format + 1] = "val = val .. '" .. op.text .. "'"
|
||||
elseif op.tag == "multiply" then
|
||||
format[#format + 1] = "val = val * " .. op.text
|
||||
elseif op.tag == "divide" then
|
||||
format[#format + 1] = "val = val / " .. op.text
|
||||
elseif op.tag == "sum" then
|
||||
format[#format + 1] = "val = 0"
|
||||
for num2, col in ipairs(op) do
|
||||
param[#param + 1] = col["id"]
|
||||
if col["format"] then
|
||||
local colform = check_format(col["format"])
|
||||
format[#format + 1] = colform .. " val = val + tempform(val)"
|
||||
else
|
||||
format[#format + 1] = "val = val + param[" .. #param .. "]"
|
||||
end
|
||||
end
|
||||
elseif op.tag == "concat" then
|
||||
format[#format + 1] = "val = ''"
|
||||
for num2, col in ipairs(op) do
|
||||
if col["tag"] == "txt" then
|
||||
format[#format + 1] = "val = val .. '" .. col["text"] .. "'"
|
||||
elseif col["format"] then
|
||||
param[#param + 1] = col["id"]
|
||||
local n = #param
|
||||
format[#format + 1] = function() return " " .. check_format(col["format"]) .. " val = val .. tempform(param[" .. n .. "])" end
|
||||
else
|
||||
param[#param + 1] = col["id"]
|
||||
format[#format + 1] = "val = val .. param[" .. #param .. "]"
|
||||
end
|
||||
end
|
||||
elseif op.tag == "min" then
|
||||
format[#format + 1] = "val = 0x7fffffffffffffff"
|
||||
for num2, col in ipairs(op) do
|
||||
param[#param + 1] = col["id"]
|
||||
format[#format + 1] = "val = math.min(val, param[" .. #param .. "])"
|
||||
end
|
||||
elseif op.tag == "max" then
|
||||
format[#format + 1] = "val = 0"
|
||||
for num2, col in ipairs(op) do
|
||||
param[#param + 1] = col["id"]
|
||||
format[#format + 1] = "val = math.max(val, param[" .. #param .. "])"
|
||||
end
|
||||
elseif op.tag == "pad" then
|
||||
format[#format + 1] = "if type(val) == 'number' then val = tostring(val) end"
|
||||
format[#format + 1] = "if #val < " .. op.max .. " then"
|
||||
if op.direction == "left" then
|
||||
format[#format + 1] = "val = string.rep('" .. op.text .. "', " .. op.max .. " - #val) .. val"
|
||||
elseif op.direction == "right" then
|
||||
format[#format + 1] = "val = val .. string.rep('" .. op.text .. "', " .. op.max .. " - #val)"
|
||||
end
|
||||
format[#format + 1] = "end"
|
||||
elseif op.tag == "trim" then
|
||||
if op.direction == "left" or op.direction == "both" then
|
||||
format[#format + 1] = "val = val:gsub('^(" .. op.text .. "*)', '')"
|
||||
end
|
||||
if op.direction == "right" or op.direction == "both" then
|
||||
format[#format + 1] = "val = val:gsub('(" .. op.text .. "*)$', '')"
|
||||
end
|
||||
elseif op.tag == "substract" then
|
||||
format[#format + 1] = "val = val - " .. op.text
|
||||
elseif op.tag == "remainder" then
|
||||
format[#format + 1] = "val = val % " .. op.text
|
||||
elseif op.tag == "trunc" then
|
||||
format[#format + 1] = "val = math.floor(val)"
|
||||
elseif op.tag == "round" then
|
||||
format[#format + 1] = "val = math.floor(val + 0.5)"
|
||||
elseif op.tag == "divide_trunc" then
|
||||
format[#format + 1] = "val = math.floor(val / " .. op.text .. ")"
|
||||
elseif op.tag == "divide_round" then
|
||||
format[#format + 1] = "val = math.floor((val / " .. op.text .. ") + 0.5)"
|
||||
elseif op.tag == "replace" then
|
||||
format[#format + 1] = "val = val:gsub('" .. op.src .. "', '" .. op.dst .. "')"
|
||||
elseif op.tag == "shift" then
|
||||
format[#format + 1] = "val = val << " .. op.text
|
||||
elseif op.tag == "lowercase" then
|
||||
format[#format + 1] = "val = val:lower()"
|
||||
elseif op.tag == "uppercase" then
|
||||
format[#format + 1] = "val = val:upper()"
|
||||
elseif op.tag == "capitalize" then
|
||||
format[#format + 1] = "val = val:gsub('^(.)', function(s) return s:upper() end)"
|
||||
elseif op.tag == "loopindex" then
|
||||
param[#param + 1] = "loopindex"
|
||||
format[#format + 1] = "val = param[" .. #param .. "]"
|
||||
elseif op.tag == "case" then
|
||||
format[#format + 1] = "val = temp"
|
||||
if not tonumber(op["src"]) then
|
||||
op["src"] = "'" .. op["src"] .. "'"
|
||||
end
|
||||
if not tonumber(op["dst"]) then
|
||||
op["dst"] = "'" .. op["dst"] .. "'"
|
||||
end
|
||||
if op["default"] == "yes" then
|
||||
format[#format + 1] = "local default = " .. op["dst"]
|
||||
end
|
||||
if op["operator-format"] then
|
||||
format[#format + 1] = function() return " val = ".. check_format(col["operator-format"]) end
|
||||
end
|
||||
if not op["operator"] then
|
||||
op["operator"] = "=="
|
||||
else
|
||||
op["operator"] = op["operator"]:gsub("<", "<")
|
||||
op["operator"] = op["operator"]:gsub(">", ">")
|
||||
end
|
||||
format[#format + 1] = "if val " .. op["operator"] .. " " .. op["src"] .. " then"
|
||||
format[#format + 1] = "val = " .. op["dst"]
|
||||
if op["format"] then
|
||||
format[#format + 1] = function() return " val = ".. check_format(col["operator-format"]) end
|
||||
end
|
||||
format[#format + 1] = "return val\n end"
|
||||
end
|
||||
|
||||
end
|
||||
fparam[form["id"]] = param
|
||||
if form["apply-to"] == "char" then
|
||||
format[#format + 1] = "if default then\nreturn default\nend\nreturn val\nend)\nreturn val\nend"
|
||||
else
|
||||
format[#format + 1] = "if default then\nreturn default\nend\nreturn val\nend"
|
||||
end
|
||||
if form["formatter"] then
|
||||
format[#format + 1] = "return string.format('" .. form["formatter"] .. "', tempform(val))\nend"
|
||||
end
|
||||
format[#format + 1] = ","
|
||||
end
|
||||
for num, line in ipairs(format) do
|
||||
if type(line) == "string" then
|
||||
s[#s + 1] = line
|
||||
elseif type(line) == "function" then
|
||||
s[#s + 1] = line()
|
||||
end
|
||||
end
|
||||
s[#s + 1] = "}"
|
||||
end
|
||||
local function parse_elem(elem, loopelem)
|
||||
local ret = 0
|
||||
if elem["tag"] == "loop" then
|
||||
if elem["skip-first-bytes"] then
|
||||
s[#s + 1] = "offset = offset + " .. elem["skip-first-bytes"]
|
||||
end
|
||||
s[#s + 1] = "for i = 1, " .. elem["count"] .. " do"
|
||||
for num, elt in ipairs(elem) do
|
||||
index = parse_elem(elt, elem)
|
||||
end
|
||||
s[#s + 1] = "end"
|
||||
if elem["skip-last-bytes"] then
|
||||
s[#s + 1] = "offset = offset + " .. elem["skip-last-bytes"]
|
||||
end
|
||||
elseif elem["tag"] == "elt" then
|
||||
s[#s + 1] = "if not arr['" .. elem["id"] .. "'] then arr['" .. elem["id"] .. "'] = {} end\nelem = {}"
|
||||
s[#s + 1] = "bytes = table.pack(string.unpack('" .. string.rep("c1", elem["size"]) .. "', data, offset))"
|
||||
if loopelem then
|
||||
total_size = total_size + elem["size"] * loopelem["count"]
|
||||
else
|
||||
total_size = total_size + elem["size"]
|
||||
end
|
||||
s[#s + 1] = "offset = table.remove(bytes)"
|
||||
if elem["decoding-profile"] then
|
||||
if elem["decoding-profile"] == "base-40" then
|
||||
elem["src-unit-size"] = 16
|
||||
elem["base"] = "40"
|
||||
elem["dst-unit-size"] = 3
|
||||
elem["ascii-offset"] = 64
|
||||
elseif elem["decoding-profile"] == "base-32" then
|
||||
elem["src-unit-size"] = 16
|
||||
elem["base"] = "32"
|
||||
elem["dst-unit-size"] = 3
|
||||
elem["ascii-offset"] = 64
|
||||
elseif elem["decoding-profile"] == "bcd" then
|
||||
elem["endianness"] = "big-endian"
|
||||
elem["nibble-skip"] = "odd"
|
||||
elem["base"] = "16"
|
||||
elseif elem["decoding-profile"] == "bcd-le" then
|
||||
elem["endianness"] = "big-endian"
|
||||
elem["nibble-skip"] = "odd"
|
||||
elem["base"] = "16"
|
||||
end
|
||||
end
|
||||
local bytedec = elem["swap-skip-order"] or "byte-swap;bit-swap;byte-skip;endianness;byte-trim;nibble-skip;bitmask"
|
||||
local bytedecl = {}
|
||||
bytedec:gsub("([^;]*)", function(c) bytedecl[#bytedecl + 1] = c end)
|
||||
for num, func in ipairs(bytedecl) do
|
||||
if elem[func] then
|
||||
fixfunc = func:gsub("-", "_")
|
||||
if func == "bitmask" then
|
||||
s[#s + 1] = "bytes = " .. fixfunc .. "(bytes, bitmask['" .. elem[func] .. "'])"
|
||||
else
|
||||
s[#s + 1] = "bytes = " .. fixfunc .. "(bytes, '" .. elem[func] .. "')"
|
||||
end
|
||||
end
|
||||
end
|
||||
if elem["type"] == "int" then
|
||||
s[#s + 1] = "value = string.unpack('>I' .. #bytes, table.concat(bytes))"
|
||||
elem["base"] = elem["base"] or "10"
|
||||
if elem["base"] == "16" then
|
||||
s[#s + 1] = "value = frombcd(value)"
|
||||
end
|
||||
s[#s + 1] = "elem.val = value"
|
||||
elseif elem["type"] == "text" then
|
||||
if elem["ascii-step"] then
|
||||
s[#s + 1] = "bytes = ascii_step(bytes, " .. elem["ascii-step"] .. ")"
|
||||
end
|
||||
if elem["ascii-offset"] then
|
||||
s[#s + 1] = "bytes = ascii_offset(bytes, " .. elem["ascii-offset"] .. ")"
|
||||
end
|
||||
if elem["base"] then
|
||||
s[#s + 1] = "bytes = basechar(bytes, " .. elem["base"] .. ")"
|
||||
end
|
||||
if elem["charset"] then
|
||||
local charsets = {}
|
||||
elem["charset"]:gsub("([^;]*)", function(s) charsets[#charsets + 1] = s return "" end)
|
||||
for num, charset in pairs(charsets) do
|
||||
if charset:match("^CS_") then
|
||||
s[#s + 1] = "bytes = charset_conv(bytes, " .. charset .. ")"
|
||||
elseif charset ~= "" then
|
||||
s[#s + 1] = "bytes = charset_conv(bytes, charset['" .. charset .. "'])"
|
||||
end
|
||||
end
|
||||
end
|
||||
s[#s + 1] = "elem.val = table.concat(bytes)"
|
||||
end
|
||||
local index
|
||||
if elem["table-index"] then
|
||||
index = tonumber(elem["table-index"])
|
||||
end
|
||||
if not index and loopelem then
|
||||
local total = loopelem["count"]
|
||||
local start = loopelem["start"] or 0
|
||||
local step = loopelem["step"] or 1
|
||||
local ref, reftype
|
||||
if elem["table-index"] then
|
||||
elem["table-index"]:match("([%w ]*):([%a_]*)")
|
||||
end
|
||||
if not elem["table-index"] or elem["table-index"] == "loop_index" then
|
||||
index = "(i - 1) * " .. step .. " + " .. start
|
||||
elseif elem["table-index"] == "loop_reverse_index" then
|
||||
index = "(" .. total .. "- i) * " .. step .. " + " .. start
|
||||
elseif elem["table-index"] == "itself" then
|
||||
index = "value"
|
||||
elseif elem["table-index"] == "last" then
|
||||
index = "lastindex"
|
||||
elseif reftype then
|
||||
index = reftype .. "(arr, '" .. ref .. "')"
|
||||
end
|
||||
end
|
||||
if index then
|
||||
s[#s + 1] = "elem.index = " .. index
|
||||
s[#s + 1] = "lastindex = elem.index"
|
||||
end
|
||||
s[#s + 1] = "arr['" .. elem["id"] .. "'][#arr['" .. elem["id"] .. "'] + 1] = elem"
|
||||
end
|
||||
return index
|
||||
end
|
||||
for num, elem in ipairs(xml.structure[1]) do
|
||||
if elem["tag"] == "loop" or elem["tag"] == "elt" then
|
||||
parse_elem(elem)
|
||||
end
|
||||
end
|
||||
table.insert(s, 1, "size = " .. total_size)
|
||||
|
||||
s[#s + 1] = "output = ''"
|
||||
|
||||
for num1, fld in ipairs(xml.output[1]) do
|
||||
if not fld["display"] or fld["display"] == "always" then
|
||||
if fld["tag"] == "field" then
|
||||
if not fld["src"] then
|
||||
fld["src"] = fld["id"]
|
||||
end
|
||||
s[#s + 1] = "output = output .. '" .. fld["id"] .. " '"
|
||||
s[#s + 1] = "val = arr['" .. fld["src"] .. "'][1]"
|
||||
if fld["format"] then
|
||||
s[#s + 1] = check_format(fld["format"])
|
||||
s[#s + 1] = "val = tempform(val)"
|
||||
end
|
||||
s[#s + 1] = "output = output .. val .. '\\n'"
|
||||
elseif fld["tag"] == "table" then
|
||||
local head = {}
|
||||
local dat = {}
|
||||
local loopcnt
|
||||
local igncol, ignval
|
||||
if fld["line-ignore"] then
|
||||
igncol, ignval = fld["line-ignore"]:match("([^:]*):(.*)")
|
||||
end
|
||||
for num2, col in ipairs(fld["column"]) do
|
||||
if not col["display"] or col["display"] == "always" then
|
||||
if not col["src"] then
|
||||
col["src"] = col["id"]
|
||||
end
|
||||
if not loopcnt and col["src"] ~= "index" then
|
||||
table.insert(dat, 1, "for i = 1, #arr['" .. col["src"] .. "'] do")
|
||||
table.insert(dat, 2, "index = arr['" .. col["src"] .. "'][i].index")
|
||||
table.insert(dat, 3, "line = ''")
|
||||
loopcnt = true
|
||||
end
|
||||
head[#head + 1] = "output = output .. '" .. col["id"] .. "\\t'"
|
||||
if col["src"] == "index" then
|
||||
dat[#dat + 1] = "val = index"
|
||||
else
|
||||
dat[#dat + 1] = "if arr['" .. col["src"] .. "'] then val = arr['" .. col["src"] .. "'][i].val end"
|
||||
end
|
||||
if col["format"] then
|
||||
dat[#dat + 1] = check_format(col["format"])
|
||||
dat[#dat + 1] = "val = tempform(val)"
|
||||
end
|
||||
if igncol == col["id"] then
|
||||
dat[#dat + 1] = "checkval = val"
|
||||
end
|
||||
dat[#dat + 1] = "line = line .. val .. '\\t'"
|
||||
end
|
||||
end
|
||||
if igncol then
|
||||
dat[#dat + 1] = "if checkval ~= " .. ignval .. " then output = output .. line .. '\\n' end\nend"
|
||||
else
|
||||
dat[#dat + 1] = "output = output .. line .. '\\n'\nend"
|
||||
end
|
||||
s[#s + 1] = table.concat(head, "\n") .. "\noutput = output .. '\\n'"
|
||||
s[#s + 1] = table.concat(dat, "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
s[#s + 1] = "return output"
|
||||
|
||||
-- cache script
|
||||
local script = table.concat(s, "\n")
|
||||
local scrpath = datpath .. "/"
|
||||
local scrfile = io.open(scrpath .. set .. ".lua", "w+")
|
||||
if not scrfile then
|
||||
lfs.mkdir(scrpath)
|
||||
scrfile = io.open(scrpath .. set .. ".lua", "w+")
|
||||
end
|
||||
if scrfile then
|
||||
scrfile:write(script)
|
||||
end
|
||||
return script
|
||||
end
|
||||
|
||||
if #env == 0 then
|
||||
function env.open(file, size)
|
||||
if file == ".hi" then
|
||||
local path = "hi"
|
||||
local ini = emu.file(lfs.env_replace(manager:options().entries.inipath:value()), 1)
|
||||
local ret = ini:open("hiscore.ini")
|
||||
if not ret then
|
||||
local inifile = ini:read(ini:size())
|
||||
for line in inifile:gmatch("[^\n\r]") do
|
||||
token, value = string.match(line, '([^ ]+) ([^ ]+)');
|
||||
if token == "hi_path" then
|
||||
path = value
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
file = path .. "/" .. set .. ".hi"
|
||||
else
|
||||
file = lfs.env_replace(manager:options().entries.nvram_directory:value()) .. "/" .. set .. "/" .. file
|
||||
end
|
||||
local f = io.open(file, "rb")
|
||||
local content = f:read("*all")
|
||||
f:close()
|
||||
if #content < size then
|
||||
content = content .. string.rep("\0", size - #content)
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
function env.endianness(bytes, endian)
|
||||
local newbytes = {}
|
||||
if endian == "little_endian" then
|
||||
for i = 1, #bytes do
|
||||
newbytes[i] = bytes[#bytes - i + 1]
|
||||
end
|
||||
else
|
||||
newbytes = bytes
|
||||
end
|
||||
return newbytes
|
||||
end
|
||||
|
||||
function env.byte_skip(bytes, skip)
|
||||
local newbytes = {}
|
||||
if skip == "odd" then
|
||||
-- lua lists are 1 based so use even indexes
|
||||
for i = 2, #bytes, 2 do
|
||||
newbytes[i/2] = bytes[i]
|
||||
end
|
||||
elseif skip == "even" then
|
||||
for i = 1, #bytes, 2 do
|
||||
newbytes[(i+1)/2] = bytes[i]
|
||||
end
|
||||
elseif skip == "1000" then
|
||||
for i = 1, #bytes, 4 do
|
||||
newbytes[(i+3)/4] = bytes[i]
|
||||
end
|
||||
elseif skip == "0100" then
|
||||
for i = 2, #bytes, 4 do
|
||||
newbytes[(i+2)/4] = bytes[i]
|
||||
end
|
||||
elseif skip == "0010" then
|
||||
for i = 3, #bytes, 4 do
|
||||
newbytes[(i+1)/4] = bytes[i]
|
||||
end
|
||||
elseif skip == "0001" then
|
||||
for i = 4, #bytes, 4 do
|
||||
newbytes[i/4] = bytes[i]
|
||||
end
|
||||
else
|
||||
skip = tonumber(skip)
|
||||
for i = 1, #bytes do
|
||||
if bytes[i] ~= skip then
|
||||
newbytes[#newbytes + 1] = bytes[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
return newbytes
|
||||
end
|
||||
|
||||
function env.byte_trim(bytes, val)
|
||||
val = tonumber(val)
|
||||
for i = 1, #bytes do
|
||||
if bytes[i] ~= val then
|
||||
return bytes
|
||||
end
|
||||
table.remove(bytes, 1)
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function env.byte_swap(bytes, val)
|
||||
local newbytes = {}
|
||||
val = tonumber(val)
|
||||
for i = 1, #bytes do
|
||||
local off = i + val - 1 - 2 * ((i - 1) % val)
|
||||
if off > #bytes then -- ??
|
||||
break
|
||||
end
|
||||
newbytes[i] = bytes[off]
|
||||
end
|
||||
return newbytes
|
||||
end
|
||||
|
||||
function env.nibble_skip(bytes, skip)
|
||||
local newbytes = {}
|
||||
if skip == "odd" then
|
||||
for i = 1, #bytes, 2 do
|
||||
val = bytes[i]:byte(1)
|
||||
newbytes[(i+1)/2] = string.char(((val & 0x0f) << 4) | (val & 0x0f))
|
||||
end
|
||||
elseif skip == "even" then
|
||||
for i = 1, #bytes, 2 do
|
||||
val = bytes[i]:byte(1)
|
||||
newbytes[(i+1)/2] = string.char((val & 0xf0) | ((val & 0xf0) >> 4))
|
||||
end
|
||||
end
|
||||
return newbytes
|
||||
end
|
||||
|
||||
function env.bit_swap(bytes, swap)
|
||||
if swap == "yes" then
|
||||
for i = 1, #bytes do
|
||||
val = bytes[i]:byte(1)
|
||||
bytes[i] = string.char(((val & 1) << 7) | ((val & 2) << 5) | ((val & 4) << 3) | ((val & 8) << 1) | ((val & 0x10) >> 1) | ((val & 0x20) >> 3) | ((val & 0x40) >> 5) | ((val & 0x80) >> 7))
|
||||
end
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function env.bitmask(bytes, mask)
|
||||
local newbytes = 0
|
||||
bytes = string.unpack(">I" .. #bytes, table.concat(bytes))
|
||||
for i = 1, #mask do
|
||||
newbytes = newbytes | (((bytes >> mask.ishift) & mask.mask) << mask.oshift)
|
||||
end
|
||||
bytes = {}
|
||||
while newbytes ~= 0 do
|
||||
bytes[#bytes + 1] = newbytes & 0xff
|
||||
newbytes = newbytes >> 8
|
||||
end
|
||||
newbytes = {}
|
||||
for i = 1, #bytes do
|
||||
newbytes[i] = string.char(bytes[#bytes + 1 - i])
|
||||
end
|
||||
return newbytes
|
||||
end
|
||||
|
||||
function env.frombcd(val)
|
||||
local result = 0
|
||||
local mul = 1
|
||||
while val ~= 0 do
|
||||
result = result + ((val % 16) * mul)
|
||||
val = val >> 4
|
||||
mul = mul * 10
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function env.basechar(bytes, base)
|
||||
if base == "32" then
|
||||
elseif base == "40" then
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function env.charset_conv(bytes, charset)
|
||||
if type(charset) == "string" then
|
||||
local chartype, offset, delta = charset:match("CS_(%w*)%[?(%-?%d?%d?),?(%d?%d?)%]?")
|
||||
if chartype == "NUMBER" then
|
||||
|
||||
end
|
||||
return
|
||||
end
|
||||
for num, char in ipairs(bytes) do
|
||||
char = string.byte(char)
|
||||
if charset[char] then
|
||||
bytes[num] = charset[char]
|
||||
elseif charset.default then
|
||||
bytes[num] = charset.default
|
||||
end
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function env.ascii_step(bytes, step)
|
||||
for num, char in ipairs(bytes) do
|
||||
bytes[num] = string.char(char:byte() / step)
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
function env.ascii_offset(bytes, offset)
|
||||
for num, char in ipairs(bytes) do
|
||||
bytes[num] = string.char(char:byte() + offset)
|
||||
end
|
||||
return bytes
|
||||
end
|
||||
|
||||
env.tostring = tostring
|
||||
env.type = type
|
||||
env.table = { pack = table.pack, concat = table.concat, insert = table.insert, remove = table.remove }
|
||||
env.string = { unpack = string.unpack, format = string.format, rep = string.rep, gsub = string.gsub, lower = string.lower, upper = string.upper }
|
||||
env.math = { min = math.min, max = math.max, floor = math.floor }
|
||||
end
|
||||
|
||||
if curset == set then
|
||||
if output then
|
||||
return "High Scores"
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
output = nil
|
||||
curset = set
|
||||
|
||||
local scrfile = emu.file(lfs.env_replace(mame_manager:ui():options().entries.historypath:value():gsub("([^;]+)", "%1/hi2txt")), 1)
|
||||
local ret = scrfile:open(set .. ".lua")
|
||||
local script
|
||||
if ret then
|
||||
local xml = xml_parse()
|
||||
if not xml then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, script = pcall(parse_table, xml)
|
||||
if not status then
|
||||
emu.print_verbose("error creating hi score parse script: " .. script)
|
||||
return nil
|
||||
end
|
||||
else
|
||||
script = scrfile:read(scrfile:size())
|
||||
end
|
||||
local scr, err = load(script, script, "t", env)
|
||||
if err then
|
||||
emu.print_verbose("error loading hi score script file: " .. err)
|
||||
else
|
||||
status, output = pcall(scr, xml_table)
|
||||
if not status then
|
||||
emu.print_verbose("error in hi score parse script: " .. output)
|
||||
output = nil
|
||||
end
|
||||
end
|
||||
if output then
|
||||
return "High Scores"
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return output
|
||||
end
|
||||
|
||||
return dat
|
22
plugins/data/data_history.lua
Normal file
22
plugins/data/data_history.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local dat = {}
|
||||
local ver, info
|
||||
local datread = require("data/load_dat")
|
||||
datread, ver = datread.open("history.dat", "## REVISION:")
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if not datread then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, info = pcall(datread, "bio", softlist or "info", set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
return "History"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
22
plugins/data/data_mameinfo.lua
Normal file
22
plugins/data/data_mameinfo.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local dat = {}
|
||||
local ver, info
|
||||
local datread = require("data/load_dat")
|
||||
datread, ver = datread.open("mameinfo.dat", "# MAMEINFO.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 "Mameinfo"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
23
plugins/data/data_messinfo.lua
Normal file
23
plugins/data/data_messinfo.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local dat = {}
|
||||
local ver, info
|
||||
|
||||
local datread = require("data/load_dat")
|
||||
datread, ver = datread.open("messinfo.dat", "# MESSINFO.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 "Messinfo"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
28
plugins/data/data_story.lua
Normal file
28
plugins/data/data_story.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local dat = {}
|
||||
local ver, info
|
||||
local datread = require("data/load_dat")
|
||||
local space_wid = mame_manager:ui():get_char_width(0x200a)
|
||||
datread, ver = datread.open("story.dat", "# version")
|
||||
|
||||
function dat.check(set, softlist)
|
||||
if softlist or not datread then
|
||||
return nil
|
||||
end
|
||||
local status
|
||||
status, info = pcall(datread, "story", "info", set)
|
||||
if not status or not info then
|
||||
return nil
|
||||
end
|
||||
info = "#jf\n" .. info:gsub("([^%s]-)(%f[_]_+%f[0-9])([0-9.]+)",
|
||||
function(name, sep, score)
|
||||
local wid = mame_manager:ui():get_string_width(name .. score, 1.0)
|
||||
return name .. string.rep(utf8.char(0x200a), math.floor((.4 - wid) / space_wid)) .. score
|
||||
end)
|
||||
return "Mamescore"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
22
plugins/data/data_sysinfo.lua
Normal file
22
plugins/data/data_sysinfo.lua
Normal file
@ -0,0 +1,22 @@
|
||||
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 "Sysinfo"
|
||||
end
|
||||
|
||||
function dat.get()
|
||||
return info
|
||||
end
|
||||
|
||||
return dat
|
60
plugins/data/init.lua
Normal file
60
plugins/data/init.lua
Normal file
@ -0,0 +1,60 @@
|
||||
-- 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 = {}
|
||||
exports.name = "data"
|
||||
exports.version = "0.0.1"
|
||||
exports.description = "Data plugin"
|
||||
exports.license = "The BSD 3-Clause License"
|
||||
exports.author = { name = "Carl" }
|
||||
|
||||
local data = exports
|
||||
|
||||
function data.set_folder(path)
|
||||
data.path = path
|
||||
end
|
||||
|
||||
function data.startplugin()
|
||||
local data_scr = {}
|
||||
local valid_lst = {}
|
||||
emu.register_start(function()
|
||||
for file in lfs.dir(data.path) do
|
||||
local name = string.match(file, "^(data_.*).lua$")
|
||||
if name then
|
||||
local script = require("data/" .. name)
|
||||
if script then
|
||||
data_scr[#data_scr + 1] = script
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
emu.register_callback(function(set)
|
||||
local ret = ""
|
||||
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
|
||||
if ret == "" then
|
||||
ret = name
|
||||
else
|
||||
ret = ret .. "," .. name
|
||||
end
|
||||
valid_lst[#valid_lst + 1] = scr
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end, "data_list")
|
||||
|
||||
emu.register_callback(function(num)
|
||||
return valid_lst[num + 1].get()
|
||||
end, "data")
|
||||
end
|
||||
|
||||
return exports
|
97
plugins/data/load_dat.lua
Normal file
97
plugins/data/load_dat.lua
Normal file
@ -0,0 +1,97 @@
|
||||
local datfile = {}
|
||||
|
||||
function datfile.open(file, vertag)
|
||||
local data = {}
|
||||
local ver
|
||||
local filepath
|
||||
local fh
|
||||
for path in mame_manager:ui():options().entries.historypath:value():gmatch("([^;]+)") do
|
||||
filepath = lfs.env_replace(path) .. "/" .. file
|
||||
fh = io.open(filepath, "rb")
|
||||
if fh then
|
||||
break
|
||||
end
|
||||
end
|
||||
if not fh then
|
||||
return nil
|
||||
end
|
||||
do
|
||||
local inblock = false
|
||||
local buffer = fh:read("a")
|
||||
if vertag then
|
||||
local match = buffer:match("^" .. vertag .. "%s([^%s]+)")
|
||||
if match then
|
||||
ver = match
|
||||
end
|
||||
end
|
||||
local function gmatchpos()
|
||||
local pos = 1
|
||||
local function iter()
|
||||
local spos, epos = buffer:find("\n$", pos, true)
|
||||
if not spos then
|
||||
return nil
|
||||
end
|
||||
spos = spos + 1
|
||||
local spos, epos, match = buffer:find("([^\n]+)", spos)
|
||||
pos = epos + 1
|
||||
return match, pos, iter
|
||||
end
|
||||
return iter
|
||||
end
|
||||
for line, epos, iter in gmatchpos() do
|
||||
|
||||
local flag = line:sub(1, 1)
|
||||
if flag ~= "#" then
|
||||
if flag == "$" then
|
||||
if line:sub(1, 4) == "$end" then
|
||||
inblock = false
|
||||
elseif not inblock then
|
||||
local tag, set = line:match("^%$([^%s=]+)=?([^%s]*)")
|
||||
if set and set ~= "" then
|
||||
local tags = {}
|
||||
local sets = {}
|
||||
local tag1 = ""
|
||||
tag:gsub("([^,]+)", function(s) tags[#tags + 1] = s end)
|
||||
set:gsub("([^,]+)", function(s) sets[#sets + 1] = s end)
|
||||
repeat
|
||||
tag1, epos = iter()
|
||||
until tag1:sub(1, 1) == "$"
|
||||
tag1 = tag1:match("^$([^%s]*)")
|
||||
if not data[tag1] then
|
||||
data[tag1] = {}
|
||||
end
|
||||
for num1, tag2 in pairs(tags) do
|
||||
if not data[tag1][tag2] then
|
||||
data[tag1][tag2] = {}
|
||||
end
|
||||
for num2, set in pairs(sets) do
|
||||
data[tag1][tag2][set] = epos
|
||||
end
|
||||
end
|
||||
end
|
||||
inblock = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
fh:close()
|
||||
fh = io.open(filepath, "r")
|
||||
local function read(tag1, tag2, set)
|
||||
local output = {}
|
||||
if not data[tag1][tag2][set] then
|
||||
return nil
|
||||
end
|
||||
fh:seek("set", data[tag1][tag2][set])
|
||||
for line in fh:lines() do
|
||||
if line == "$end" then
|
||||
return table.concat(output, "\n")
|
||||
end
|
||||
output[#output + 1] = line
|
||||
end
|
||||
end
|
||||
|
||||
return read, ver
|
||||
end
|
||||
|
||||
return datfile
|
10
plugins/data/plugin.json
Normal file
10
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"
|
||||
}
|
||||
}
|
@ -2280,6 +2280,17 @@ int lua_engine::l_osd_printf_debug(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_engine::l_driver_find(lua_State *L)
|
||||
{
|
||||
luaL_argcheck(L, lua_isstring(L, 1), 1, "message (string) expected");
|
||||
int index = driver_list::find(lua_tostring(L, 1));
|
||||
if(index == -1)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
luabridge::Stack<const game_driver &>::push(L, driver_list::driver(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// initialize - initialize lua hookup to emu engine
|
||||
//-------------------------------------------------
|
||||
@ -2316,6 +2327,7 @@ void lua_engine::initialize()
|
||||
.addCFunction ("print_error", l_osd_printf_error )
|
||||
.addCFunction ("print_info", l_osd_printf_info )
|
||||
.addCFunction ("print_debug", l_osd_printf_debug )
|
||||
.addCFunction ("driver_find", l_driver_find )
|
||||
.beginClass <machine_manager>("manager")
|
||||
.addFunction("machine", &machine_manager::machine)
|
||||
.addFunction("options", &machine_manager::options)
|
||||
@ -2577,6 +2589,8 @@ void lua_engine::initialize()
|
||||
.addProperty <bool, bool> ("show_profiler", &mame_ui_manager::show_profiler, &mame_ui_manager::set_show_profiler)
|
||||
.addProperty <bool, bool> ("single_step", &mame_ui_manager::single_step, &mame_ui_manager::set_single_step)
|
||||
.addFunction ("get_line_height", &mame_ui_manager::get_line_height)
|
||||
.addFunction ("get_string_width", &mame_ui_manager::get_string_width)
|
||||
.addFunction ("get_char_width", &mame_ui_manager::get_char_width)
|
||||
.endClass()
|
||||
.beginClass <lua_screen> ("lua_screen_dev")
|
||||
.addCFunction ("draw_box", &lua_screen::l_draw_box)
|
||||
|
@ -143,6 +143,7 @@ private:
|
||||
static int l_osd_printf_error(lua_State *L);
|
||||
static int l_osd_printf_info(lua_State *L);
|
||||
static int l_osd_printf_debug(lua_State *L);
|
||||
static int l_driver_find(lua_State *L);
|
||||
static int register_function(lua_State *L, const char *id);
|
||||
|
||||
// "emu.machine" namespace
|
||||
|
@ -33,23 +33,9 @@
|
||||
#include "rendutil.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "uiinput.h"
|
||||
|
||||
extern const char UI_VERSION_TAG[];
|
||||
|
||||
namespace ui {
|
||||
namespace {
|
||||
char const *const dats_info[] = {
|
||||
__("General Info"),
|
||||
__("History"),
|
||||
__("Mameinfo"),
|
||||
__("Sysinfo"),
|
||||
__("Messinfo"),
|
||||
__("Command"),
|
||||
__("Gameinit"),
|
||||
__("Mamescore")
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool menu_select_game::first_start = true;
|
||||
std::vector<const game_driver *> menu_select_game::m_sortedlist;
|
||||
@ -61,10 +47,6 @@ int menu_select_game::m_isabios = 0;
|
||||
|
||||
menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &container, const char *gamename)
|
||||
: menu_select_launch(mui, container, false)
|
||||
, m_info_buffer()
|
||||
, m_info_driver(nullptr)
|
||||
, m_info_software(nullptr)
|
||||
, m_info_view(-1)
|
||||
{
|
||||
highlight = 0;
|
||||
std::string error_string, last_filter, sub_filter;
|
||||
@ -139,10 +121,11 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta
|
||||
mui.machine().options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
|
||||
|
||||
ui_globals::curimage_view = FIRST_VIEW;
|
||||
ui_globals::curdats_view = UI_FIRST_LOAD;
|
||||
ui_globals::curdats_view = 0;
|
||||
ui_globals::switch_image = false;
|
||||
ui_globals::default_image = true;
|
||||
ui_globals::panels_status = moptions.hide_panels();
|
||||
ui_globals::curdats_total = 1;
|
||||
m_searchlist[0] = nullptr;
|
||||
}
|
||||
|
||||
@ -270,7 +253,7 @@ void menu_select_game::handle()
|
||||
if (!isfavorite())
|
||||
{
|
||||
const game_driver *drv = (const game_driver *)menu_event->itemref;
|
||||
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view > UI_FIRST_LOAD)
|
||||
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view > 0)
|
||||
{
|
||||
ui_globals::curdats_view--;
|
||||
m_topline_datsview = 0;
|
||||
@ -279,7 +262,7 @@ void menu_select_game::handle()
|
||||
else
|
||||
{
|
||||
ui_software_info *drv = (ui_software_info *)menu_event->itemref;
|
||||
if (drv->startempty == 1 && ui_globals::curdats_view > UI_FIRST_LOAD)
|
||||
if (drv->startempty == 1 && ui_globals::curdats_view > 0)
|
||||
{
|
||||
ui_globals::curdats_view--;
|
||||
m_topline_datsview = 0;
|
||||
@ -308,7 +291,7 @@ void menu_select_game::handle()
|
||||
if (!isfavorite())
|
||||
{
|
||||
const game_driver *drv = (const game_driver *)menu_event->itemref;
|
||||
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view < UI_LAST_LOAD)
|
||||
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view < ui_globals::curdats_total)
|
||||
{
|
||||
ui_globals::curdats_view++;
|
||||
m_topline_datsview = 0;
|
||||
@ -317,12 +300,12 @@ void menu_select_game::handle()
|
||||
else
|
||||
{
|
||||
ui_software_info *drv = (ui_software_info *)menu_event->itemref;
|
||||
if (drv->startempty == 1 && ui_globals::curdats_view < UI_LAST_LOAD)
|
||||
if (drv->startempty == 1 && ui_globals::curdats_view < ui_globals::curdats_total)
|
||||
{
|
||||
ui_globals::curdats_view++;
|
||||
m_topline_datsview = 0;
|
||||
}
|
||||
else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view < 1)
|
||||
else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view < ui_globals::cur_sw_dats_total)
|
||||
{
|
||||
ui_globals::cur_sw_dats_view++;
|
||||
m_topline_datsview = 0;
|
||||
@ -1272,7 +1255,7 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
|
||||
if (cloneof != -1)
|
||||
util::stream_format(str, _("Driver is Clone of: %1$-.100s\n"), driver_list::driver(cloneof).description);
|
||||
else
|
||||
str << _("Driver is Parent\n");
|
||||
str << _("Driver is Parent:\n");
|
||||
|
||||
if (driver->flags & MACHINE_NOT_WORKING)
|
||||
str << _("Overall: NOT WORKING\n");
|
||||
@ -1340,6 +1323,24 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
|
||||
else
|
||||
str << _("Roms Audit Pass: Disabled\nSamples Audit Pass: Disabled\n");
|
||||
|
||||
std::istringstream istr(str.str());
|
||||
std::string line;
|
||||
float spacewid = ui().get_char_width(0x200a);
|
||||
str.clear();
|
||||
str.seekp(0);
|
||||
str << "#jp\n";
|
||||
while(std::getline(istr, line))
|
||||
{
|
||||
int nspace = floor((0.35 - ui().get_string_width(line.c_str())) / spacewid);
|
||||
if(nspace < 5)
|
||||
nspace = 5;
|
||||
std::string newstr;
|
||||
newstr.reserve((nspace * 3) + line.length());
|
||||
newstr.append(line.substr(0, line.find(':')));
|
||||
for(int i = 0; i < nspace; i++)
|
||||
newstr.append("\xE2\x80\x8A");
|
||||
str << newstr.append(line.substr(line.find(':') + 1, line.npos)).append("\n");
|
||||
}
|
||||
buffer = str.str();
|
||||
}
|
||||
|
||||
@ -1660,312 +1661,6 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// draw infos
|
||||
//-------------------------------------------------
|
||||
|
||||
void menu_select_game::infos_render(float origx1, float origy1, float origx2, float origy2)
|
||||
{
|
||||
float const line_height = ui().get_line_height();
|
||||
float text_size = ui().options().infos_size();
|
||||
std::vector<int> xstart;
|
||||
std::vector<int> xend;
|
||||
|
||||
ui_software_info const *software;
|
||||
game_driver const *driver;
|
||||
get_selection(software, driver);
|
||||
|
||||
if (software && ((software->startempty != 1) || !driver))
|
||||
{
|
||||
m_info_driver = nullptr;
|
||||
|
||||
float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
|
||||
float ud_arrow_width = line_height * machine().render().ui_aspect();
|
||||
float oy1 = origy1 + line_height;
|
||||
|
||||
// apply title to right panel
|
||||
if (software->usage.empty())
|
||||
{
|
||||
ui().draw_text_full(container(), _("History"), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
|
||||
mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
|
||||
ui_globals::cur_sw_dats_view = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float title_size = 0.0f;
|
||||
float txt_length = 0.0f;
|
||||
std::string t_text[2];
|
||||
t_text[0] = _("History");
|
||||
t_text[1] = _("Usage");
|
||||
|
||||
for (auto & elem: t_text)
|
||||
{
|
||||
ui().draw_text_full(container(), elem.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
|
||||
mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
|
||||
txt_length += 0.01f;
|
||||
title_size = (std::max)(txt_length, title_size);
|
||||
}
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
if (get_focus() == focused_menu::rightbottom)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
float middle = origx2 - origx1;
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
{
|
||||
ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
|
||||
origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
|
||||
}
|
||||
|
||||
ui().draw_text_full(container(), t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1,
|
||||
ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
|
||||
|
||||
draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size);
|
||||
}
|
||||
|
||||
if (m_info_software != software || m_info_view != ui_globals::cur_sw_dats_view)
|
||||
{
|
||||
m_info_buffer.clear();
|
||||
m_info_view = ui_globals::cur_sw_dats_view;
|
||||
m_info_software = software;
|
||||
if (ui_globals::cur_sw_dats_view == 0)
|
||||
{
|
||||
if (software->startempty == 1)
|
||||
mame_machine_manager::instance()->datfile().load_data_info(software->driver, m_info_buffer, UI_HISTORY_LOAD);
|
||||
else
|
||||
mame_machine_manager::instance()->datfile().load_software_info(software->listname, m_info_buffer, software->shortname, software->parentname);
|
||||
}
|
||||
else
|
||||
m_info_buffer = software->usage;
|
||||
}
|
||||
|
||||
if (m_info_buffer.empty())
|
||||
{
|
||||
ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
}
|
||||
|
||||
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
|
||||
if (m_total_lines < r_visible_lines)
|
||||
r_visible_lines = m_total_lines;
|
||||
if (m_topline_datsview < 0)
|
||||
m_topline_datsview = 0;
|
||||
if (m_topline_datsview + r_visible_lines >= m_total_lines)
|
||||
m_topline_datsview = m_total_lines - r_visible_lines;
|
||||
|
||||
for (int r = 0; r < r_visible_lines; ++r)
|
||||
{
|
||||
int itemline = r + m_topline_datsview;
|
||||
std::string tempbuf(m_info_buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
|
||||
|
||||
// up arrow
|
||||
if (r == 0 && m_topline_datsview != 0)
|
||||
draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
// bottom arrow
|
||||
else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
|
||||
draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
else
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
|
||||
oy1 += (line_height * text_size);
|
||||
}
|
||||
|
||||
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
|
||||
right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
|
||||
}
|
||||
else if (driver)
|
||||
{
|
||||
m_info_software = nullptr;
|
||||
|
||||
float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
|
||||
float ud_arrow_width = line_height * machine().render().ui_aspect();
|
||||
float oy1 = origy1 + line_height;
|
||||
|
||||
// MAMESCORE? Full size text
|
||||
if (ui_globals::curdats_view == UI_STORY_LOAD)
|
||||
text_size = 1.0f;
|
||||
|
||||
std::string snaptext(_(dats_info[ui_globals::curdats_view]));
|
||||
|
||||
// apply title to right panel
|
||||
float title_size = 0.0f;
|
||||
float txt_length = 0.0f;
|
||||
|
||||
for (int x = UI_FIRST_LOAD; x < UI_LAST_LOAD; ++x)
|
||||
{
|
||||
ui().draw_text_full(container(), _(dats_info[x]), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::NEVER, mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
|
||||
txt_length += 0.01f;
|
||||
title_size = (std::max)(txt_length, title_size);
|
||||
}
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
if (get_focus() == focused_menu::rightbottom)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
float middle = origx2 - origx1;
|
||||
|
||||
// check size
|
||||
float sc = title_size + 2.0f * gutter_width;
|
||||
float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
|
||||
title_size *= tmp_size;
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
{
|
||||
ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
|
||||
origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
|
||||
}
|
||||
|
||||
ui().draw_text_full(container(), snaptext.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
|
||||
|
||||
draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curdats_view, UI_FIRST_LOAD, UI_LAST_LOAD, title_size);
|
||||
|
||||
if (driver != m_info_driver || ui_globals::curdats_view != m_info_view)
|
||||
{
|
||||
m_info_buffer.clear();
|
||||
m_info_driver = driver;
|
||||
m_info_view = ui_globals::curdats_view;
|
||||
m_topline_datsview = 0;
|
||||
m_total_lines = 0;
|
||||
std::vector<std::string> m_item;
|
||||
|
||||
if (ui_globals::curdats_view == UI_GENERAL_LOAD)
|
||||
general_info(driver, m_info_buffer);
|
||||
else if (ui_globals::curdats_view != UI_COMMAND_LOAD)
|
||||
mame_machine_manager::instance()->datfile().load_data_info(driver, m_info_buffer, ui_globals::curdats_view);
|
||||
else
|
||||
mame_machine_manager::instance()->datfile().command_sub_menu(driver, m_item);
|
||||
|
||||
if (!m_item.empty() && ui_globals::curdats_view == UI_COMMAND_LOAD)
|
||||
{
|
||||
for (size_t x = 0; x < m_item.size(); ++x)
|
||||
{
|
||||
std::string t_buffer;
|
||||
m_info_buffer.append(m_item[x]).append("\n");
|
||||
mame_machine_manager::instance()->datfile().load_command_info(t_buffer, m_item[x]);
|
||||
if (!t_buffer.empty())
|
||||
m_info_buffer.append(t_buffer).append("\n");
|
||||
}
|
||||
convert_command_glyph(m_info_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info_buffer.empty())
|
||||
{
|
||||
ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
else if (ui_globals::curdats_view != UI_STORY_LOAD && ui_globals::curdats_view != UI_COMMAND_LOAD)
|
||||
m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
else
|
||||
m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
|
||||
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
|
||||
if (m_total_lines < r_visible_lines)
|
||||
r_visible_lines = m_total_lines;
|
||||
if (m_topline_datsview < 0)
|
||||
m_topline_datsview = 0;
|
||||
if (m_topline_datsview + r_visible_lines >= m_total_lines)
|
||||
m_topline_datsview = m_total_lines - r_visible_lines;
|
||||
|
||||
sc = origx2 - origx1 - (2.0f * UI_BOX_LR_BORDER);
|
||||
for (int r = 0; r < r_visible_lines; ++r)
|
||||
{
|
||||
int itemline = r + m_topline_datsview;
|
||||
std::string tempbuf(m_info_buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
|
||||
|
||||
// up arrow
|
||||
if (r == 0 && m_topline_datsview != 0)
|
||||
draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
// bottom arrow
|
||||
else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
|
||||
draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
// special case for mamescore
|
||||
else if (ui_globals::curdats_view == UI_STORY_LOAD)
|
||||
{
|
||||
// check size
|
||||
float textlen = ui().get_string_width(tempbuf.c_str(), text_size);
|
||||
float tmp_size2 = (textlen > sc) ? text_size * (sc / textlen) : text_size;
|
||||
|
||||
size_t last_underscore = tempbuf.find_last_of("_");
|
||||
if (last_underscore == std::string::npos)
|
||||
{
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1, oy1, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size2);
|
||||
}
|
||||
else
|
||||
{
|
||||
float effective_width = origx2 - origx1 - gutter_width;
|
||||
float effective_left = origx1 + gutter_width;
|
||||
std::string last_part(tempbuf.substr(last_underscore + 1));
|
||||
std::string first_part(tempbuf.substr(0, tempbuf.find("___")));
|
||||
float item_width;
|
||||
|
||||
ui().draw_text_full(container(), first_part.c_str(), effective_left, oy1, effective_width,
|
||||
ui::text_layout::LEFT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &item_width, nullptr, tmp_size2);
|
||||
|
||||
ui().draw_text_full(container(), last_part.c_str(), effective_left + item_width, oy1,
|
||||
origx2 - origx1 - 2.0f * gutter_width - item_width, ui::text_layout::RIGHT, ui::text_layout::TRUNCATE,
|
||||
mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size2);
|
||||
}
|
||||
}
|
||||
|
||||
// special case for command
|
||||
else if (ui_globals::curdats_view == UI_COMMAND_LOAD || ui_globals::curdats_view == UI_GENERAL_LOAD)
|
||||
{
|
||||
// check size
|
||||
float textlen = ui().get_string_width(tempbuf.c_str(), text_size);
|
||||
float tmp_size3 = (textlen > sc) ? text_size * (sc / textlen) : text_size;
|
||||
|
||||
int first_dspace = (ui_globals::curdats_view == UI_COMMAND_LOAD) ? tempbuf.find(" ") : tempbuf.find(":");
|
||||
if (first_dspace > 0)
|
||||
{
|
||||
float effective_width = origx2 - origx1 - gutter_width;
|
||||
float effective_left = origx1 + gutter_width;
|
||||
std::string first_part(tempbuf.substr(0, first_dspace));
|
||||
std::string last_part(tempbuf.substr(first_dspace + 1));
|
||||
strtrimspace(last_part);
|
||||
ui().draw_text_full(container(), first_part.c_str(), effective_left, oy1, effective_width, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3);
|
||||
|
||||
ui().draw_text_full(container(), last_part.c_str(), effective_left, oy1, origx2 - origx1 - 2.0f * gutter_width,
|
||||
ui::text_layout::RIGHT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
|
||||
}
|
||||
|
||||
oy1 += (line_height * text_size);
|
||||
}
|
||||
|
||||
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
|
||||
right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -1986,7 +1681,6 @@ void menu_select_game::get_selection(ui_software_info const *&software, game_dri
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const
|
||||
{
|
||||
inifile_manager &inifile = mame_machine_manager::instance()->inifile();
|
||||
|
@ -43,11 +43,6 @@ private:
|
||||
static int m_isabios;
|
||||
int highlight;
|
||||
|
||||
std::string m_info_buffer;
|
||||
game_driver const *m_info_driver;
|
||||
ui_software_info const *m_info_software;
|
||||
int m_info_view;
|
||||
|
||||
static std::vector<const game_driver *> m_sortedlist;
|
||||
std::vector<const game_driver *> m_availsortedlist;
|
||||
std::vector<const game_driver *> m_unavailsortedlist;
|
||||
@ -88,9 +83,7 @@ private:
|
||||
}
|
||||
|
||||
// General info
|
||||
void general_info(const game_driver *driver, std::string &buffer);
|
||||
|
||||
virtual void infos_render(float x1, float y1, float x2, float y2) override;
|
||||
virtual void general_info(const game_driver *driver, std::string &buffer) override;
|
||||
|
||||
// handlers
|
||||
void inkey_select(const event *menu_event);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "rendutil.h"
|
||||
#include "softlist.h"
|
||||
#include "uiinput.h"
|
||||
#include "luaengine.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -153,6 +154,10 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c
|
||||
, m_total_lines(0)
|
||||
, m_topline_datsview(0)
|
||||
, m_ui_error(false)
|
||||
, m_info_driver(nullptr)
|
||||
, m_info_software(nullptr)
|
||||
, m_info_view(-1)
|
||||
, m_info_buffer()
|
||||
, m_cache()
|
||||
, m_is_swlist(is_swlist)
|
||||
, m_focus(focused_menu::main)
|
||||
@ -1871,4 +1876,211 @@ void menu_select_launch::exit(running_machine &machine)
|
||||
s_caches.erase(&machine);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// draw infos
|
||||
//-------------------------------------------------
|
||||
|
||||
void menu_select_launch::infos_render(float origx1, float origy1, float origx2, float origy2)
|
||||
{
|
||||
float const line_height = ui().get_line_height();
|
||||
float text_size = ui().options().infos_size();
|
||||
std::vector<int> xstart;
|
||||
std::vector<int> xend;
|
||||
const char *first = "";
|
||||
ui_software_info const *software;
|
||||
game_driver const *driver;
|
||||
int total;
|
||||
get_selection(software, driver);
|
||||
|
||||
if (software && ((software->startempty != 1) || !driver))
|
||||
{
|
||||
m_info_driver = nullptr;
|
||||
first = "Usage";
|
||||
|
||||
if (m_info_software != software || m_info_view != ui_globals::cur_sw_dats_view)
|
||||
{
|
||||
m_info_buffer.clear();
|
||||
if (software == m_info_software)
|
||||
{
|
||||
m_info_view = ui_globals::cur_sw_dats_view;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_info_view = 0;
|
||||
m_info_software = software;
|
||||
ui_globals::cur_sw_dats_view = 0;
|
||||
ui_globals::cur_sw_dats_total = 1;
|
||||
|
||||
const char *lua_list = mame_machine_manager::instance()->lua()->call_plugin(std::string(software->shortname).append(1, ',').append(software->listname).c_str(), "data_list");
|
||||
m_items_list.clear();
|
||||
if(lua_list)
|
||||
{
|
||||
std::string list(lua_list);
|
||||
char *token = strtok((char *)list.c_str(), ",");
|
||||
while(token)
|
||||
{
|
||||
ui_globals::cur_sw_dats_total++;
|
||||
m_items_list.emplace_back(token);
|
||||
token = strtok(nullptr, ",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info_view == 0)
|
||||
m_info_buffer = software->usage;
|
||||
else
|
||||
m_info_buffer = mame_machine_manager::instance()->lua()->call_plugin(util::string_format("%d", m_info_view - 1).c_str(), "data");
|
||||
}
|
||||
total = ui_globals::cur_sw_dats_total;
|
||||
}
|
||||
else if (driver)
|
||||
{
|
||||
m_info_software = nullptr;
|
||||
first = "General Info";
|
||||
|
||||
if (driver != m_info_driver || ui_globals::curdats_view != m_info_view)
|
||||
{
|
||||
m_info_buffer.clear();
|
||||
if (driver == m_info_driver)
|
||||
{
|
||||
m_info_view = ui_globals::curdats_view;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_info_driver = driver;
|
||||
m_info_view = 0;
|
||||
ui_globals::curdats_view = 0;
|
||||
ui_globals::curdats_total = 1;
|
||||
|
||||
const char *lua_list = mame_machine_manager::instance()->lua()->call_plugin(driver->name, "data_list");
|
||||
m_items_list.clear();
|
||||
if(lua_list)
|
||||
{
|
||||
std::string list(lua_list);
|
||||
char *token = strtok((char *)list.c_str(), ",");
|
||||
while(token)
|
||||
{
|
||||
ui_globals::curdats_total++;
|
||||
m_items_list.emplace_back(token);
|
||||
token = strtok(nullptr, ",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info_view == 0)
|
||||
general_info(driver, m_info_buffer);
|
||||
else
|
||||
m_info_buffer = mame_machine_manager::instance()->lua()->call_plugin(util::string_format("%d", m_info_view - 1).c_str(), "data");
|
||||
}
|
||||
total = ui_globals::curdats_total;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
|
||||
float ud_arrow_width = line_height * machine().render().ui_aspect();
|
||||
float oy1 = origy1 + line_height;
|
||||
|
||||
std::string snaptext;
|
||||
if (m_info_view)
|
||||
snaptext = _(m_items_list[m_info_view - 1].c_str());
|
||||
else
|
||||
snaptext = _(first);
|
||||
|
||||
// apply title to right panel
|
||||
float title_size = 0.0f;
|
||||
float txt_length = 0.0f;
|
||||
|
||||
for (int x = 0; x < ui_globals::curdats_total; ++x)
|
||||
{
|
||||
const char *name;
|
||||
if(!x)
|
||||
name = first;
|
||||
else
|
||||
name = m_items_list[x - 1].c_str();
|
||||
ui().draw_text_full(container(), _(name), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::NEVER, mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
|
||||
txt_length += 0.01f;
|
||||
title_size = (std::max)(txt_length, title_size);
|
||||
}
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
if (get_focus() == focused_menu::rightbottom)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
float middle = origx2 - origx1;
|
||||
|
||||
// check size
|
||||
float sc = title_size + 2.0f * gutter_width;
|
||||
float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
|
||||
title_size *= tmp_size;
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
{
|
||||
ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
|
||||
origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
|
||||
}
|
||||
|
||||
ui().draw_text_full(container(), snaptext.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
|
||||
|
||||
char justify = 'l'; // left justify
|
||||
if ((m_info_buffer.length() >= 3) && (m_info_buffer[0] == '#'))
|
||||
{
|
||||
if (m_info_buffer[1] == 'j')
|
||||
justify = m_info_buffer[2];
|
||||
}
|
||||
|
||||
draw_common_arrow(origx1, origy1, origx2, origy2, m_info_view, 0, total - 1, title_size);
|
||||
if (justify == 'f')
|
||||
m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
else
|
||||
m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
|
||||
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
|
||||
if (m_total_lines < r_visible_lines)
|
||||
r_visible_lines = m_total_lines;
|
||||
if (m_topline_datsview < 0)
|
||||
m_topline_datsview = 0;
|
||||
if (m_topline_datsview + r_visible_lines >= m_total_lines)
|
||||
m_topline_datsview = m_total_lines - r_visible_lines;
|
||||
|
||||
sc = origx2 - origx1 - (2.0f * UI_BOX_LR_BORDER);
|
||||
for (int r = 0; r < r_visible_lines; ++r)
|
||||
{
|
||||
int itemline = r + m_topline_datsview;
|
||||
std::string tempbuf(m_info_buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
|
||||
if (tempbuf[0] == '#')
|
||||
continue;
|
||||
|
||||
// up arrow
|
||||
if (r == 0 && m_topline_datsview != 0)
|
||||
draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
// bottom arrow
|
||||
else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
|
||||
draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
else if (justify == 'f' || justify == 'p') // full or partial justify
|
||||
{
|
||||
// check size
|
||||
float textlen = ui().get_string_width(tempbuf.c_str(), text_size);
|
||||
float tmp_size3 = (textlen > sc) ? text_size * (sc / textlen) : text_size;
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
|
||||
ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
|
||||
}
|
||||
|
||||
oy1 += (line_height * text_size);
|
||||
}
|
||||
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
|
||||
right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -115,8 +115,15 @@ private:
|
||||
// draw left panel
|
||||
virtual float draw_left_panel(float x1, float y1, float x2, float y2) = 0;
|
||||
|
||||
game_driver const *m_info_driver;
|
||||
ui_software_info const *m_info_software;
|
||||
int m_info_view;
|
||||
std::vector<std::string> m_items_list;
|
||||
std::string m_info_buffer;
|
||||
|
||||
// draw infos
|
||||
virtual void infos_render(float x1, float y1, float x2, float y2) = 0;
|
||||
void infos_render(float x1, float y1, float x2, float y2);
|
||||
virtual void general_info(const game_driver *driver, std::string &buffer) = 0;
|
||||
|
||||
// get selected software and/or driver
|
||||
virtual void get_selection(ui_software_info const *&software, game_driver const *&driver) const = 0;
|
||||
|
@ -142,7 +142,8 @@ menu_select_software::menu_select_software(mame_ui_manager &mui, render_containe
|
||||
|
||||
ui_globals::curimage_view = SNAPSHOT_VIEW;
|
||||
ui_globals::switch_image = true;
|
||||
ui_globals::cur_sw_dats_view = UI_FIRST_LOAD;
|
||||
ui_globals::cur_sw_dats_view = 0;
|
||||
ui_globals::cur_sw_dats_total = 1;
|
||||
|
||||
std::string error_string;
|
||||
mui.machine().options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string);
|
||||
@ -224,7 +225,7 @@ void menu_select_software::handle()
|
||||
ui_globals::switch_image = true;
|
||||
ui_globals::default_image = false;
|
||||
}
|
||||
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
|
||||
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < ui_globals::cur_sw_dats_total)
|
||||
{
|
||||
// Infos
|
||||
ui_globals::cur_sw_dats_view++;
|
||||
@ -339,7 +340,7 @@ void menu_select_software::handle()
|
||||
ui_globals::switch_image = true;
|
||||
ui_globals::default_image = false;
|
||||
}
|
||||
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
|
||||
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < ui_globals::cur_sw_dats_total)
|
||||
{
|
||||
// Infos
|
||||
ui_globals::cur_sw_dats_view++;
|
||||
@ -1258,151 +1259,6 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// draw infos
|
||||
//-------------------------------------------------
|
||||
|
||||
void menu_select_software::infos_render(float origx1, float origy1, float origx2, float origy2)
|
||||
{
|
||||
float line_height = ui().get_line_height();
|
||||
static std::string buffer;
|
||||
std::vector<int> xstart;
|
||||
std::vector<int> xend;
|
||||
float text_size = ui().options().infos_size();
|
||||
ui_software_info *soft = (get_selection_ref() != nullptr) ? (ui_software_info *)get_selection_ref() : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr);
|
||||
static ui_software_info *oldsoft = nullptr;
|
||||
static int old_sw_view = -1;
|
||||
|
||||
float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
|
||||
float ud_arrow_width = line_height * machine().render().ui_aspect();
|
||||
float oy1 = origy1 + line_height;
|
||||
|
||||
// apply title to right panel
|
||||
if (soft != nullptr && soft->usage.empty())
|
||||
{
|
||||
float title_size = 0.0f;
|
||||
|
||||
ui().draw_text_full(container(), _("History"), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
|
||||
mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &title_size, nullptr);
|
||||
title_size += 0.01f;
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
if (get_focus() == focused_menu::rightbottom)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
float middle = origx2 - origx1;
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
|
||||
origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
|
||||
|
||||
ui().draw_text_full(container(), _("History"), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::NEVER,
|
||||
mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
|
||||
ui_globals::cur_sw_dats_view = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float title_size = 0.0f;
|
||||
float txt_lenght = 0.0f;
|
||||
std::string t_text[2];
|
||||
t_text[0] = _("History");
|
||||
t_text[1] = _("Usage");
|
||||
|
||||
for (auto & elem : t_text)
|
||||
{
|
||||
ui().draw_text_full(container(), elem.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::NEVER,
|
||||
mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr);
|
||||
txt_lenght += 0.01f;
|
||||
title_size = std::max(txt_lenght, title_size);
|
||||
}
|
||||
|
||||
rgb_t fgcolor = UI_TEXT_COLOR;
|
||||
rgb_t bgcolor = UI_TEXT_BG_COLOR;
|
||||
if (get_focus() == focused_menu::rightbottom)
|
||||
{
|
||||
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
|
||||
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
float middle = origx2 - origx1;
|
||||
|
||||
// check size
|
||||
float sc = title_size + 2.0f * gutter_width;
|
||||
float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
|
||||
title_size *= tmp_size;
|
||||
|
||||
if (bgcolor != UI_TEXT_BG_COLOR)
|
||||
ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
|
||||
origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
|
||||
|
||||
ui().draw_text_full(container(), t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1,
|
||||
ui::text_layout::CENTER, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
|
||||
|
||||
draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size);
|
||||
}
|
||||
|
||||
if (oldsoft != soft || old_sw_view != ui_globals::cur_sw_dats_view)
|
||||
{
|
||||
buffer.clear();
|
||||
old_sw_view = ui_globals::cur_sw_dats_view;
|
||||
oldsoft = soft;
|
||||
if (ui_globals::cur_sw_dats_view == 0)
|
||||
{
|
||||
if (soft->startempty == 1)
|
||||
mame_machine_manager::instance()->datfile().load_data_info(soft->driver, buffer, UI_HISTORY_LOAD);
|
||||
else
|
||||
mame_machine_manager::instance()->datfile().load_software_info(soft->listname, buffer, soft->shortname, soft->parentname);
|
||||
}
|
||||
else
|
||||
buffer = soft->usage;
|
||||
}
|
||||
|
||||
if (buffer.empty())
|
||||
{
|
||||
ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER,
|
||||
ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_total_lines = ui().wrap_text(container(), buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
|
||||
|
||||
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
|
||||
if (m_total_lines < r_visible_lines)
|
||||
r_visible_lines = m_total_lines;
|
||||
if (m_topline_datsview < 0)
|
||||
m_topline_datsview = 0;
|
||||
if (m_topline_datsview + r_visible_lines >= m_total_lines)
|
||||
m_topline_datsview = m_total_lines - r_visible_lines;
|
||||
|
||||
for (int r = 0; r < r_visible_lines; ++r)
|
||||
{
|
||||
int itemline = r + m_topline_datsview;
|
||||
std::string tempbuf;
|
||||
tempbuf.assign(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
|
||||
|
||||
// up arrow
|
||||
if (r == 0 && m_topline_datsview != 0)
|
||||
draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
// bottom arrow
|
||||
else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
|
||||
draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
|
||||
else
|
||||
ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1,
|
||||
ui::text_layout::LEFT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR,
|
||||
nullptr, nullptr, text_size);
|
||||
oy1 += (line_height * text_size);
|
||||
}
|
||||
|
||||
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
|
||||
right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ctor
|
||||
//-------------------------------------------------
|
||||
|
@ -61,11 +61,11 @@ private:
|
||||
void find_matches(const char *str, int count);
|
||||
void load_sw_custom_filters();
|
||||
|
||||
virtual void infos_render(float x1, float y1, float x2, float y2) override;
|
||||
|
||||
// handlers
|
||||
void inkey_select(const event *menu_event);
|
||||
void inkey_special(const event *menu_event);
|
||||
|
||||
virtual void general_info(const game_driver *driver, std::string &buffer) override {}
|
||||
};
|
||||
|
||||
class software_parts : public menu
|
||||
|
@ -40,6 +40,8 @@ size_t sw_filters::length = ARRAY_LENGTH(sw_filters::text);
|
||||
UINT8 ui_globals::rpanel = 0;
|
||||
UINT8 ui_globals::curimage_view = 0;
|
||||
UINT8 ui_globals::curdats_view = 0;
|
||||
UINT8 ui_globals::cur_sw_dats_total = 0;
|
||||
UINT8 ui_globals::curdats_total = 0;
|
||||
UINT8 ui_globals::cur_sw_dats_view = 0;
|
||||
bool ui_globals::switch_image = false;
|
||||
bool ui_globals::default_image = true;
|
||||
|
@ -202,7 +202,7 @@ struct c_year
|
||||
// GLOBAL CLASS
|
||||
struct ui_globals
|
||||
{
|
||||
static UINT8 curimage_view, curdats_view, cur_sw_dats_view, rpanel;
|
||||
static UINT8 curimage_view, curdats_view, curdats_total, cur_sw_dats_view, cur_sw_dats_total, rpanel;
|
||||
static bool switch_image, redraw_icon, default_image, reset;
|
||||
static int visible_main_lines, visible_sw_lines;
|
||||
static UINT16 panels_status;
|
||||
|
Loading…
Reference in New Issue
Block a user