osd/modules/file: Don't magically substitute environment variables when opening files. (#9859)

* util/options.cpp: Added option types for single and multiple paths.
* util/options.cpp: Substitute environment variables in values from defaults and INI files.
* ui/dirmenu.cpp: Removed hard-coded list of multi-path options.
* plugins: Don't substitute environment variables in path options.
This commit is contained in:
npwoods 2022-12-16 14:03:59 -05:00 committed by GitHub
parent 14c3d33e86
commit 13910382a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 367 additions and 192 deletions

View File

@ -1,7 +1,7 @@
local lib = {}
local function get_settings_path()
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/autofire'
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/autofire'
end
local function get_settings_filename()

View File

@ -8,7 +8,7 @@ _G.N_ = function (message) return message end
_G.N_p = function (context, message) return message end
_G.emu.plugin = {} -- table to contain plugin interfaces
-- substitute environment variables in the plugins path from options
local dirs = emu.subst_env(manager.options.entries.pluginspath:value())
local dirs = manager.options.entries.pluginspath:value()
-- and split the paths apart and make them suitable for package.path
package.path = ""

View File

@ -130,7 +130,7 @@ function cheat.startplugin()
local function load_hotkeys()
local json = require("json")
local file = io.open(emu.subst_env(manager.machine.options.entries.cheatpath:value():match("([^;]+)")) .. "/" .. cheatname .. "_hotkeys.json", "r")
local file = io.open(manager.machine.options.entries.cheatpath:value():match("([^;]+)") .. "/" .. cheatname .. "_hotkeys.json", "r")
if not file then
return
end
@ -154,7 +154,7 @@ function cheat.startplugin()
end
end
end
local path = emu.subst_env(manager.machine.options.entries.cheatpath:value():match("([^;]+)"))
local path = manager.machine.options.entries.cheatpath:value():match("([^;]+)")
local filepath = path .. "/" .. cheatname .. "_hotkeys.json"
if #hotkeys > 0 then
local json = require("json")

View File

@ -965,7 +965,7 @@ function cheatfind.startplugin()
end
end
end
cheat_save.path = emu.subst_env(manager.machine.options.entries.cheatpath:value()):match("([^;]+)")
cheat_save.path = manager.machine.options.entries.cheatpath:value():match("([^;]+)")
cheat_save.filename = string.format("%s/%s", cheat_save.path, setname)
cheat_save.name = cheat.desc
local json = require("json")

View File

@ -243,7 +243,7 @@ function console.startplugin()
end
if (not started) then
-- options are not available in startplugin, so we load the history here
local homepath = emu.subst_env(manager.options.entries.homepath:value():match("([^;]+)"))
local homepath = manager.options.entries.homepath:value():match("([^;]+)")
history_fullpath = homepath .. '/' .. history_file
ln.loadhistory(history_fullpath)
started = true

View File

@ -5,7 +5,7 @@ local dat = {}
local env = {}
local output
local curset
local path = emu.subst_env(mame_manager.ui.options.entries.historypath:value():gsub("([^;]+)", "%1/hi2txt"))
local path = mame_manager.ui.options.entries.historypath:value():gsub("([^;]+)", "%1/hi2txt")
local htmlentites = {
["amp"] = "&",
["quot"] = utf8.char(34),
@ -355,7 +355,7 @@ local htmlentites = {
function env.open(file, size, swap)
if file == ".hi" then
local path = "hi"
local ini = emu.file(emu.subst_env(manager.options.entries.inipath:value()), 1)
local ini = emu.file(manager.options.entries.inipath:value(), 1)
local ret = ini:open("hiscore.ini")
if not ret then
local inifile = ini:read(ini:size())
@ -369,7 +369,7 @@ function env.open(file, size, swap)
end
file = path .. "/" .. curset .. ".hi"
else
file = emu.subst_env(manager.options.entries.nvram_directory:value()) .. "/" .. curset .. "/" .. file
file = manager.options.entries.nvram_directory:value() .. "/" .. curset .. "/" .. file
end
local f = io.open(file, "rb")
local content = f:read("*all")

View File

@ -10,7 +10,7 @@ local function check_db_result(msg)
end
local function settings_path()
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/data'
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/data'
end
local function check_version_table()
@ -147,7 +147,7 @@ end
function dbtable.open_data_file(file)
local fh, filepath
for path in mame_manager.ui.options.entries.historypath:value():gmatch('([^;]+)') do
filepath = emu.subst_env(path) .. '/' .. file
filepath = path .. '/' .. file
fh = io.open(filepath, 'r')
if fh then
break

View File

@ -23,7 +23,7 @@ end
function hiscore.startplugin()
local function get_data_path()
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/hiscore'
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/hiscore'
end
-- configuration

View File

@ -5,7 +5,7 @@
-- Helpers
local function settings_path()
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/inputmacro'
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/inputmacro'
end
local function settings_filename()

View File

@ -28,7 +28,7 @@ local portname = exports
function portname.startplugin()
local json = require("json")
local ctrlrpath = emu.subst_env(manager.options.entries.ctrlrpath:value():match("([^;]+)"))
local ctrlrpath = manager.options.entries.ctrlrpath:value():match("([^;]+)")
local function get_filename(nosoft)
local filename
if emu.softname() ~= "" and not nosoft then

View File

@ -34,7 +34,7 @@ function timecode.startplugin()
local function get_settings_path()
return emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/timecode'
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/timecode'
end

View File

@ -130,7 +130,7 @@ end
local function open_database()
-- make sure settings directory exists
local dir = emu.subst_env(manager.machine.options.entries.homepath:value():match('([^;]+)')) .. '/timer'
local dir = manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/timer'
local attr = lfs.attributes(dir)
if not attr then
lfs.mkdir(dir)

View File

@ -37,30 +37,30 @@ const options_entry emu_options::s_option_entries[] =
// search path options
{ nullptr, nullptr, core_options::option_type::HEADER, "CORE SEARCH PATH OPTIONS" },
{ OPTION_PLUGINDATAPATH, ".", core_options::option_type::STRING, "path to base folder for plugin data (read/write)" },
{ OPTION_MEDIAPATH ";rp;biospath;bp", "roms", core_options::option_type::STRING, "path to ROM sets and hard disk images" },
{ OPTION_HASHPATH ";hash_directory;hash", "hash", core_options::option_type::STRING, "path to software definition files" },
{ OPTION_SAMPLEPATH ";sp", "samples", core_options::option_type::STRING, "path to audio sample sets" },
{ OPTION_ARTPATH, "artwork", core_options::option_type::STRING, "path to artwork files" },
{ OPTION_CTRLRPATH, "ctrlr", core_options::option_type::STRING, "path to controller definitions" },
{ OPTION_INIPATH, ".;ini;ini/presets", core_options::option_type::STRING, "path to ini files" },
{ OPTION_FONTPATH, ".", core_options::option_type::STRING, "path to font files" },
{ OPTION_CHEATPATH, "cheat", core_options::option_type::STRING, "path to cheat files" },
{ OPTION_CROSSHAIRPATH, "crosshair", core_options::option_type::STRING, "path to crosshair files" },
{ OPTION_PLUGINSPATH, "plugins", core_options::option_type::STRING, "path to plugin files" },
{ OPTION_LANGUAGEPATH, "language", core_options::option_type::STRING, "path to UI translation files" },
{ OPTION_SWPATH, "software", core_options::option_type::STRING, "path to loose software" },
{ OPTION_PLUGINDATAPATH, ".", core_options::option_type::PATH, "path to base folder for plugin data (read/write)" },
{ OPTION_MEDIAPATH ";rp;biospath;bp", "roms", core_options::option_type::MULTIPATH, "path to ROM sets and hard disk images" },
{ OPTION_HASHPATH ";hash_directory;hash", "hash", core_options::option_type::MULTIPATH, "path to software definition files" },
{ OPTION_SAMPLEPATH ";sp", "samples", core_options::option_type::MULTIPATH, "path to audio sample sets" },
{ OPTION_ARTPATH, "artwork", core_options::option_type::MULTIPATH, "path to artwork files" },
{ OPTION_CTRLRPATH, "ctrlr", core_options::option_type::MULTIPATH, "path to controller definitions" },
{ OPTION_INIPATH, ".;ini;ini/presets", core_options::option_type::MULTIPATH, "path to ini files" },
{ OPTION_FONTPATH, ".", core_options::option_type::MULTIPATH, "path to font files" },
{ OPTION_CHEATPATH, "cheat", core_options::option_type::MULTIPATH, "path to cheat files" },
{ OPTION_CROSSHAIRPATH, "crosshair", core_options::option_type::MULTIPATH, "path to crosshair files" },
{ OPTION_PLUGINSPATH, "plugins", core_options::option_type::MULTIPATH, "path to plugin files" },
{ OPTION_LANGUAGEPATH, "language", core_options::option_type::MULTIPATH, "path to UI translation files" },
{ OPTION_SWPATH, "software", core_options::option_type::MULTIPATH, "path to loose software" },
// output directory options
{ nullptr, nullptr, core_options::option_type::HEADER, "CORE OUTPUT DIRECTORY OPTIONS" },
{ OPTION_CFG_DIRECTORY, "cfg", core_options::option_type::STRING, "directory to save configurations" },
{ OPTION_NVRAM_DIRECTORY, "nvram", core_options::option_type::STRING, "directory to save NVRAM contents" },
{ OPTION_INPUT_DIRECTORY, "inp", core_options::option_type::STRING, "directory to save input device logs" },
{ OPTION_STATE_DIRECTORY, "sta", core_options::option_type::STRING, "directory to save states" },
{ OPTION_SNAPSHOT_DIRECTORY, "snap", core_options::option_type::STRING, "directory to save/load screenshots" },
{ OPTION_DIFF_DIRECTORY, "diff", core_options::option_type::STRING, "directory to save hard drive image difference files" },
{ OPTION_COMMENT_DIRECTORY, "comments", core_options::option_type::STRING, "directory to save debugger comments" },
{ OPTION_SHARE_DIRECTORY, "share", core_options::option_type::STRING, "directory to share with emulated machines" },
{ OPTION_CFG_DIRECTORY, "cfg", core_options::option_type::PATH, "directory to save configurations" },
{ OPTION_NVRAM_DIRECTORY, "nvram", core_options::option_type::PATH, "directory to save NVRAM contents" },
{ OPTION_INPUT_DIRECTORY, "inp", core_options::option_type::PATH, "directory to save input device logs" },
{ OPTION_STATE_DIRECTORY, "sta", core_options::option_type::PATH, "directory to save states" },
{ OPTION_SNAPSHOT_DIRECTORY, "snap", core_options::option_type::PATH, "directory to save/load screenshots" },
{ OPTION_DIFF_DIRECTORY, "diff", core_options::option_type::PATH, "directory to save hard drive image difference files" },
{ OPTION_COMMENT_DIRECTORY, "comments", core_options::option_type::PATH, "directory to save debugger comments" },
{ OPTION_SHARE_DIRECTORY, "share", core_options::option_type::PATH, "directory to share with emulated machines" },
// state/playback options
{ nullptr, nullptr, core_options::option_type::HEADER, "CORE STATE/PLAYBACK OPTIONS" },
@ -72,9 +72,9 @@ const options_entry emu_options::s_option_entries[] =
{ OPTION_RECORD ";rec", nullptr, core_options::option_type::STRING, "record an input file" },
{ OPTION_EXIT_AFTER_PLAYBACK, "0", core_options::option_type::BOOLEAN, "close the program at the end of playback" },
{ OPTION_MNGWRITE, nullptr, core_options::option_type::STRING, "optional filename to write a MNG movie of the current session" },
{ OPTION_AVIWRITE, nullptr, core_options::option_type::STRING, "optional filename to write an AVI movie of the current session" },
{ OPTION_WAVWRITE, nullptr, core_options::option_type::STRING, "optional filename to write a WAV file of the current session" },
{ OPTION_MNGWRITE, nullptr, core_options::option_type::PATH, "optional filename to write a MNG movie of the current session" },
{ OPTION_AVIWRITE, nullptr, core_options::option_type::PATH, "optional filename to write an AVI movie of the current session" },
{ OPTION_WAVWRITE, nullptr, core_options::option_type::PATH, "optional filename to write a WAV file of the current session" },
{ OPTION_SNAPNAME, "%g/%i", core_options::option_type::STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" },
{ OPTION_SNAPSIZE, "auto", core_options::option_type::STRING, "specify snapshot/movie resolution (<width>x<height>) or 'auto' to use minimal size " },
{ OPTION_SNAPVIEW, "auto", core_options::option_type::STRING, "snapshot/movie view - 'auto' for default, or 'native' for per-screen pixel-aspect views" },
@ -181,7 +181,7 @@ const options_entry emu_options::s_option_entries[] =
{ OPTION_OSLOG, "0", core_options::option_type::BOOLEAN, "output error.log data to system diagnostic output (debugger or standard error)" },
{ OPTION_DEBUG ";d", "0", core_options::option_type::BOOLEAN, "enable/disable debugger" },
{ OPTION_UPDATEINPAUSE, "0", core_options::option_type::BOOLEAN, "keep calling video updates while in pause" },
{ OPTION_DEBUGSCRIPT, nullptr, core_options::option_type::STRING, "script for debugger" },
{ OPTION_DEBUGSCRIPT, nullptr, core_options::option_type::PATH, "script for debugger" },
{ OPTION_DEBUGLOG, "0", core_options::option_type::BOOLEAN, "write debug console output to debug.log" },
// comm options
@ -212,7 +212,7 @@ const options_entry emu_options::s_option_entries[] =
{ nullptr, nullptr, core_options::option_type::HEADER, "SCRIPTING OPTIONS" },
{ OPTION_AUTOBOOT_COMMAND ";ab", nullptr, core_options::option_type::STRING, "command to execute after machine boot" },
{ OPTION_AUTOBOOT_DELAY, "0", core_options::option_type::INTEGER, "delay before executing autoboot command (seconds)" },
{ OPTION_AUTOBOOT_SCRIPT ";script", nullptr, core_options::option_type::STRING, "Lua script to execute after machine boot" },
{ OPTION_AUTOBOOT_SCRIPT ";script", nullptr, core_options::option_type::PATH, "Lua script to execute after machine boot" },
{ OPTION_CONSOLE, "0", core_options::option_type::BOOLEAN, "enable emulator Lua console" },
{ OPTION_PLUGINS, "1", core_options::option_type::BOOLEAN, "enable Lua plugin support" },
{ OPTION_PLUGIN, nullptr, core_options::option_type::STRING, "list of plugins to enable" },
@ -221,7 +221,7 @@ const options_entry emu_options::s_option_entries[] =
{ nullptr, nullptr, core_options::option_type::HEADER, "HTTP SERVER OPTIONS" },
{ OPTION_HTTP, "0", core_options::option_type::BOOLEAN, "enable HTTP server" },
{ OPTION_HTTP_PORT, "8080", core_options::option_type::INTEGER, "HTTP server port" },
{ OPTION_HTTP_ROOT, "web", core_options::option_type::STRING, "HTTP server document root" },
{ OPTION_HTTP_ROOT, "web", core_options::option_type::PATH, "HTTP server document root" },
{ nullptr }
};
@ -255,7 +255,7 @@ namespace
}
protected:
virtual void internal_set_value(std::string &&newvalue) override
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override
{
m_host.set_system_name(std::move(newvalue));
}
@ -275,7 +275,7 @@ namespace
}
protected:
virtual void internal_set_value(std::string &&newvalue) override
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override
{
m_host.set_software(std::move(newvalue));
}
@ -313,7 +313,7 @@ namespace
}
protected:
virtual void internal_set_value(std::string &&newvalue) override
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override
{
m_host.specify(std::move(newvalue), false);
}
@ -339,7 +339,7 @@ namespace
}
protected:
virtual void internal_set_value(std::string &&newvalue) override
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override
{
m_host.specify(std::move(newvalue), false);
}

View File

@ -1732,7 +1732,7 @@ void cli_frontend::execute_commands(std::string_view exename)
path_iterator iter(m_options.plugins_path());
std::string pluginpath;
while (iter.next(pluginpath))
plugin_opts.scan_directory(osd_subst_env(pluginpath), true);
plugin_opts.scan_directory(pluginpath, true);
emu_file file_plugin(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
if (file_plugin.open("plugin.ini"))

View File

@ -1172,7 +1172,7 @@ void lua_engine::initialize()
e.set_value(string_format("%d", val), OPTION_PRIORITY_CMDLINE);
},
[this](core_options::entry &e, const char *val) {
if(e.type() != core_options::option_type::STRING)
if(e.type() != core_options::option_type::STRING && e.type() != core_options::option_type::PATH && e.type() != core_options::option_type::MULTIPATH)
luaL_error(m_lua_state, "Cannot set option to wrong type");
else
e.set_value(val, OPTION_PRIORITY_CMDLINE);

View File

@ -142,10 +142,7 @@ void mame_machine_manager::start_luaengine()
std::string pluginpath;
while (iter.next(pluginpath))
{
// user may specify environment variables; subsitute them
pluginpath = osd_subst_env(pluginpath);
// and then scan the directory recursively
// scan the directory recursively
m_plugins->scan_directory(pluginpath, true);
}
@ -202,7 +199,7 @@ void mame_machine_manager::start_luaengine()
std::error_condition const filerr = file.open("boot.lua");
if (!filerr)
{
const std::string exppath = osd_subst_env(file.fullpath());
const std::string exppath = file.fullpath();
auto &l(*lua());
auto load_result = l.load_script(exppath);
if (!load_result.valid())

View File

@ -29,50 +29,46 @@ namespace ui {
namespace {
constexpr int ADDING = 1;
constexpr int CHANGE = 2;
struct folders_entry
{
const char *name;
const char *option;
const int action;
};
const folders_entry f_folders[] =
{
{ N_p("path-option", "ROMs"), OPTION_MEDIAPATH, ADDING },
{ N_p("path-option", "Software Media"), OPTION_SWPATH, CHANGE },
{ N_p("path-option", "Sound Samples"), OPTION_SAMPLEPATH, ADDING },
{ N_p("path-option", "Artwork"), OPTION_ARTPATH, ADDING },
{ N_p("path-option", "Crosshairs"), OPTION_CROSSHAIRPATH, ADDING },
{ N_p("path-option", "Cheat Files"), OPTION_CHEATPATH, ADDING },
{ N_p("path-option", "Plugins"), OPTION_PLUGINSPATH, ADDING },
{ N_p("path-option", "UI Translations"), OPTION_LANGUAGEPATH, CHANGE },
{ N_p("path-option", "Software Lists"), OPTION_HASHPATH, ADDING },
{ N_p("path-option", "INIs"), OPTION_INIPATH, ADDING },
{ N_p("path-option", "UI Settings"), OPTION_UI_PATH, CHANGE },
{ N_p("path-option", "Plugin Data"), OPTION_PLUGINDATAPATH, CHANGE },
{ N_p("path-option", "DATs"), OPTION_HISTORY_PATH, ADDING },
{ N_p("path-option", "Category INIs"), OPTION_CATEGORYINI_PATH, CHANGE },
{ N_p("path-option", "Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
{ N_p("path-option", "Icons"), OPTION_ICONS_PATH, ADDING },
{ N_p("path-option", "Control Panels"), OPTION_CPANELS_PATH, ADDING },
{ N_p("path-option", "Cabinets"), OPTION_CABINETS_PATH, ADDING },
{ N_p("path-option", "Marquees"), OPTION_MARQUEES_PATH, ADDING },
{ N_p("path-option", "PCBs"), OPTION_PCBS_PATH, ADDING },
{ N_p("path-option", "Flyers"), OPTION_FLYERS_PATH, ADDING },
{ N_p("path-option", "Title Screens"), OPTION_TITLES_PATH, ADDING },
{ N_p("path-option", "Game Endings"), OPTION_ENDS_PATH, ADDING },
{ N_p("path-option", "Bosses"), OPTION_BOSSES_PATH, ADDING },
{ N_p("path-option", "Artwork Previews"), OPTION_ARTPREV_PATH, ADDING },
{ N_p("path-option", "Select"), OPTION_SELECT_PATH, ADDING },
{ N_p("path-option", "Game Over Screens"), OPTION_GAMEOVER_PATH, ADDING },
{ N_p("path-option", "HowTo"), OPTION_HOWTO_PATH, ADDING },
{ N_p("path-option", "Logos"), OPTION_LOGOS_PATH, ADDING },
{ N_p("path-option", "Scores"), OPTION_SCORES_PATH, ADDING },
{ N_p("path-option", "Versus"), OPTION_VERSUS_PATH, ADDING },
{ N_p("path-option", "Covers"), OPTION_COVER_PATH, ADDING }
{ N_p("path-option", "ROMs"), OPTION_MEDIAPATH },
{ N_p("path-option", "Software Media"), OPTION_SWPATH },
{ N_p("path-option", "Sound Samples"), OPTION_SAMPLEPATH },
{ N_p("path-option", "Artwork"), OPTION_ARTPATH },
{ N_p("path-option", "Crosshairs"), OPTION_CROSSHAIRPATH },
{ N_p("path-option", "Cheat Files"), OPTION_CHEATPATH },
{ N_p("path-option", "Plugins"), OPTION_PLUGINSPATH },
{ N_p("path-option", "UI Translations"), OPTION_LANGUAGEPATH },
{ N_p("path-option", "Software Lists"), OPTION_HASHPATH },
{ N_p("path-option", "INIs"), OPTION_INIPATH },
{ N_p("path-option", "UI Settings"), OPTION_UI_PATH },
{ N_p("path-option", "Plugin Data"), OPTION_PLUGINDATAPATH },
{ N_p("path-option", "DATs"), OPTION_HISTORY_PATH },
{ N_p("path-option", "Category INIs"), OPTION_CATEGORYINI_PATH },
{ N_p("path-option", "Snapshots"), OPTION_SNAPSHOT_DIRECTORY },
{ N_p("path-option", "Icons"), OPTION_ICONS_PATH },
{ N_p("path-option", "Control Panels"), OPTION_CPANELS_PATH },
{ N_p("path-option", "Cabinets"), OPTION_CABINETS_PATH },
{ N_p("path-option", "Marquees"), OPTION_MARQUEES_PATH },
{ N_p("path-option", "PCBs"), OPTION_PCBS_PATH },
{ N_p("path-option", "Flyers"), OPTION_FLYERS_PATH },
{ N_p("path-option", "Title Screens"), OPTION_TITLES_PATH },
{ N_p("path-option", "Game Endings"), OPTION_ENDS_PATH },
{ N_p("path-option", "Bosses"), OPTION_BOSSES_PATH },
{ N_p("path-option", "Artwork Previews"), OPTION_ARTPREV_PATH },
{ N_p("path-option", "Select"), OPTION_SELECT_PATH },
{ N_p("path-option", "Game Over Screens"), OPTION_GAMEOVER_PATH },
{ N_p("path-option", "HowTo"), OPTION_HOWTO_PATH },
{ N_p("path-option", "Logos"), OPTION_LOGOS_PATH },
{ N_p("path-option", "Scores"), OPTION_SCORES_PATH },
{ N_p("path-option", "Versus"), OPTION_VERSUS_PATH },
{ N_p("path-option", "Covers"), OPTION_COVER_PATH }
};
@ -166,7 +162,7 @@ void menu_remove_folder::populate(float &customtop, float &custombottom)
class menu_add_change_folder : public menu
{
public:
menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref);
menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref, bool multipath);
protected:
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
@ -180,9 +176,9 @@ private:
void update_search();
int const m_ref;
bool const m_multipath;
std::string m_current_path;
std::string m_search;
bool const m_change;
std::vector<std::string> m_folders;
};
@ -190,10 +186,10 @@ private:
// ctor
//-------------------------------------------------
menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref)
menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref, bool multipath)
: menu(mui, container)
, m_ref(ref)
, m_change(f_folders[ref].action == CHANGE)
, m_multipath(multipath)
{
// configure the starting path
osd_get_full_path(m_current_path, ".");
@ -255,7 +251,7 @@ void menu_add_change_folder::handle(event const *ev)
{
// Tab key, save current path
std::string error_string;
if (m_change)
if (!m_multipath)
{
if (ui().options().exists(f_folders[m_ref].option))
ui().options().set_value(f_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE);
@ -349,7 +345,7 @@ void menu_add_change_folder::custom_render(void *selectedref, float top, float b
{
std::string const toptext[] = {
util::string_format(
m_change ? _("Change %1$s Folder - Search: %2$s_") : _("Add %1$s Folder - Search: %2$s_"),
m_multipath ? _("Add %1$s Folder - Search: %2$s_") : _("Change %1$s Folder - Search: %2$s_"),
_("path-option", f_folders[m_ref].name),
m_search),
m_current_path };
@ -428,8 +424,9 @@ class menu_display_actual : public menu
public:
menu_display_actual(mame_ui_manager &mui, render_container &container, int selectedref)
: menu(mui, container)
, m_heading{ util::string_format((f_folders[selectedref].action == ADDING) ? _("%1$s Folders") : _("%1$s Folder"), _("path-option", f_folders[selectedref].name)) }
, m_ref(selectedref)
, m_multipath(is_multipath(f_folders[selectedref].option))
, m_heading{ util::string_format(m_multipath ? _("%1$s Folders") : _("%1$s Folder"), _("path-option", f_folders[selectedref].name)) }
{
}
@ -446,12 +443,29 @@ private:
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle(event const *ev) override;
bool is_multipath(std::string_view folder) const;
int const m_ref;
bool const m_multipath;
std::string const m_heading[1];
std::string m_searchpath;
std::vector<std::string> m_folders;
int const m_ref;
};
//-------------------------------------------------
// is_multipath
//-------------------------------------------------
bool menu_display_actual::is_multipath(std::string_view folder) const
{
auto option = ui().options().get_entry(folder);
if (!option)
option = machine().options().get_entry(folder);
assert(option);
return option->type() == core_options::option_type::MULTIPATH;
}
//-------------------------------------------------
// handle
//-------------------------------------------------
@ -468,7 +482,7 @@ void menu_display_actual::handle(event const *ev)
break;
case ADD_CHANGE:
menu::stack_push<menu_add_change_folder>(ui(), container(), m_ref);
menu::stack_push<menu_add_change_folder>(ui(), container(), m_ref, m_multipath);
break;
}
}
@ -480,21 +494,31 @@ void menu_display_actual::handle(event const *ev)
void menu_display_actual::populate(float &customtop, float &custombottom)
{
if (ui().options().exists(f_folders[m_ref].option))
m_searchpath.assign(ui().options().value(f_folders[m_ref].option));
else
m_searchpath.assign(machine().options().value(f_folders[m_ref].option));
auto const &folder = f_folders[m_ref];
auto option = ui().options().get_entry(folder.option);
if (!option)
option = machine().options().get_entry(folder.option);
assert(option);
m_searchpath.assign(option->value());
path_iterator path(m_searchpath);
std::string curpath;
m_folders.clear();
while (path.next(curpath))
m_folders.push_back(curpath);
if (m_multipath)
{
path_iterator path(m_searchpath);
std::string curpath;
while (path.next(curpath))
m_folders.push_back(curpath);
item_append((f_folders[m_ref].action == CHANGE) ? _("Change Folder") : _("Add Folder"), 0, (void *)ADD_CHANGE);
if (m_folders.size() > 1)
item_append(_("Remove Folder"), 0, (void *)REMOVE);
item_append(_("Add Folder"), 0, (void *)ADD_CHANGE);
if (m_folders.size() > 1)
item_append(_("Remove Folder"), 0, (void *)REMOVE);
}
else
{
m_folders.push_back(m_searchpath);
item_append(_("Change Folder"), 0, (void *)ADD_CHANGE);
}
item_append(menu_item_type::SEPARATOR);
@ -559,7 +583,7 @@ void menu_directory::handle(event const *ev)
void menu_directory::populate(float &customtop, float &custombottom)
{
for (auto & elem : f_folders)
item_append(_("path-option", elem.name), 0, (void *)(uintptr_t)elem.action);
item_append(_("path-option", elem.name), 0, this); // need a non-null reference pointer - value is immaterial
item_append(menu_item_type::SEPARATOR);
}

View File

@ -20,31 +20,31 @@
const options_entry ui_options::s_option_entries[] =
{
// search path options
{ nullptr, nullptr, core_options::option_type::HEADER, "UI SEARCH PATH OPTIONS" },
{ OPTION_HISTORY_PATH, "history;dats;.", core_options::option_type::STRING, "path to system/software info files" },
{ OPTION_CATEGORYINI_PATH, "folders", core_options::option_type::STRING, "path to category ini files" },
{ OPTION_CABINETS_PATH, "cabinets;cabdevs", core_options::option_type::STRING, "path to cabinets / devices image" },
{ OPTION_CPANELS_PATH, "cpanel", core_options::option_type::STRING, "path to control panel image" },
{ OPTION_PCBS_PATH, "pcb", core_options::option_type::STRING, "path to pcbs image" },
{ OPTION_FLYERS_PATH, "flyers", core_options::option_type::STRING, "path to flyers image" },
{ OPTION_TITLES_PATH, "titles", core_options::option_type::STRING, "path to titles image" },
{ OPTION_ENDS_PATH, "ends", core_options::option_type::STRING, "path to ends image" },
{ OPTION_MARQUEES_PATH, "marquees", core_options::option_type::STRING, "path to marquees image" },
{ OPTION_ARTPREV_PATH, "artwork preview;artpreview", core_options::option_type::STRING, "path to artwork preview image" },
{ OPTION_BOSSES_PATH, "bosses", core_options::option_type::STRING, "path to bosses image" },
{ OPTION_LOGOS_PATH, "logo", core_options::option_type::STRING, "path to logos image" },
{ OPTION_SCORES_PATH, "scores", core_options::option_type::STRING, "path to scores image" },
{ OPTION_VERSUS_PATH, "versus", core_options::option_type::STRING, "path to versus image" },
{ OPTION_GAMEOVER_PATH, "gameover", core_options::option_type::STRING, "path to gameover image" },
{ OPTION_HOWTO_PATH, "howto", core_options::option_type::STRING, "path to howto image" },
{ OPTION_SELECT_PATH, "select", core_options::option_type::STRING, "path to select image" },
{ OPTION_ICONS_PATH, "icons", core_options::option_type::STRING, "path to ICOns image" },
{ OPTION_COVER_PATH, "covers", core_options::option_type::STRING, "path to software cover image" },
{ OPTION_UI_PATH, "ui", core_options::option_type::STRING, "path to UI files" },
{ nullptr, nullptr, core_options::option_type::HEADER, "UI SEARCH PATH OPTIONS" },
{ OPTION_HISTORY_PATH, "history;dats;.", core_options::option_type::MULTIPATH, "path to system/software info files" },
{ OPTION_CATEGORYINI_PATH, "folders", core_options::option_type::MULTIPATH, "path to category ini files" },
{ OPTION_CABINETS_PATH, "cabinets;cabdevs", core_options::option_type::MULTIPATH, "path to cabinets / devices image" },
{ OPTION_CPANELS_PATH, "cpanel", core_options::option_type::MULTIPATH, "path to control panel image" },
{ OPTION_PCBS_PATH, "pcb", core_options::option_type::MULTIPATH, "path to pcbs image" },
{ OPTION_FLYERS_PATH, "flyers", core_options::option_type::MULTIPATH, "path to flyers image" },
{ OPTION_TITLES_PATH, "titles", core_options::option_type::MULTIPATH, "path to titles image" },
{ OPTION_ENDS_PATH, "ends", core_options::option_type::MULTIPATH, "path to ends image" },
{ OPTION_MARQUEES_PATH, "marquees", core_options::option_type::MULTIPATH, "path to marquees image" },
{ OPTION_ARTPREV_PATH, "artwork preview;artpreview", core_options::option_type::MULTIPATH, "path to artwork preview image" },
{ OPTION_BOSSES_PATH, "bosses", core_options::option_type::MULTIPATH, "path to bosses image" },
{ OPTION_LOGOS_PATH, "logo", core_options::option_type::MULTIPATH, "path to logos image" },
{ OPTION_SCORES_PATH, "scores", core_options::option_type::MULTIPATH, "path to scores image" },
{ OPTION_VERSUS_PATH, "versus", core_options::option_type::MULTIPATH, "path to versus image" },
{ OPTION_GAMEOVER_PATH, "gameover", core_options::option_type::MULTIPATH, "path to gameover image" },
{ OPTION_HOWTO_PATH, "howto", core_options::option_type::MULTIPATH, "path to howto image" },
{ OPTION_SELECT_PATH, "select", core_options::option_type::MULTIPATH, "path to select image" },
{ OPTION_ICONS_PATH, "icons", core_options::option_type::MULTIPATH, "path to ICOns image" },
{ OPTION_COVER_PATH, "covers", core_options::option_type::MULTIPATH, "path to software cover image" },
{ OPTION_UI_PATH, "ui", core_options::option_type::MULTIPATH, "path to UI files" },
// misc options
{ nullptr, nullptr, core_options::option_type::HEADER, "UI MISC OPTIONS" },
{ OPTION_SYSTEM_NAMES, "", core_options::option_type::STRING, "translated system names file" },
{ OPTION_SYSTEM_NAMES, "", core_options::option_type::MULTIPATH, "translated system names file" },
{ OPTION_SKIP_WARNINGS, "0", core_options::option_type::BOOLEAN, "display fewer repeated warnings about imperfect emulation" },
{ OPTION_REMEMBER_LAST, "1", core_options::option_type::BOOLEAN, "initially select last used system in main menu" },
{ OPTION_ENLARGE_SNAPS, "1", core_options::option_type::BOOLEAN, "enlarge artwork (snapshot, title, etc.) in right panel (keeping aspect ratio)" },

View File

@ -173,7 +173,7 @@ submenu::submenu(mame_ui_manager &mui, render_container &container, std::vector<
case option_type::EMU:
sm_option.entry = opts->get_entry(sm_option.name);
sm_option.options = opts;
if (sm_option.entry->type() == core_options::option_type::STRING)
if ((sm_option.entry->type() == core_options::option_type::STRING) || (sm_option.entry->type() == core_options::option_type::PATH) || (sm_option.entry->type() == core_options::option_type::MULTIPATH))
{
sm_option.value.clear();
std::string namestr(sm_option.entry->description());
@ -197,7 +197,7 @@ submenu::submenu(mame_ui_manager &mui, render_container &container, std::vector<
case option_type::OSD:
sm_option.entry = opts->get_entry(sm_option.name);
sm_option.options = opts;
if (sm_option.entry->type() == core_options::option_type::STRING)
if ((sm_option.entry->type() == core_options::option_type::STRING) || (sm_option.entry->type() == core_options::option_type::PATH) || (sm_option.entry->type() == core_options::option_type::MULTIPATH))
{
sm_option.value.clear();
std::string descr(machine().options().get_entry(sm_option.name)->description()), delim(", ");
@ -307,6 +307,8 @@ void submenu::handle(event const *ev)
}
break;
case core_options::option_type::STRING:
case core_options::option_type::PATH:
case core_options::option_type::MULTIPATH:
if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT)
{
changed = true;

View File

@ -12,6 +12,7 @@
#include "corefile.h"
#include "corestr.h"
#include "osdcore.h"
#include <locale>
#include <string>
@ -20,6 +21,7 @@
#include <cctype>
#include <cstdarg>
#include <cstdlib>
#include <sstream>
const int core_options::MAX_UNADORNED_OPTIONS;
@ -113,7 +115,7 @@ options_error_exception::options_error_exception(std::string &&message)
// entry - constructor
//-------------------------------------------------
core_options::entry::entry(std::vector<std::string> &&names, core_options::option_type type, const char *description)
core_options::entry::entry(std::vector<std::string> &&names, option_type type, const char *description)
: m_names(std::move(names))
, m_priority(OPTION_PRIORITY_DEFAULT)
, m_type(type)
@ -122,7 +124,7 @@ core_options::entry::entry(std::vector<std::string> &&names, core_options::optio
assert(m_names.empty() == (m_type == option_type::HEADER));
}
core_options::entry::entry(std::string &&name, core_options::option_type type, const char *description)
core_options::entry::entry(std::string &&name, option_type type, const char *description)
: entry(std::vector<std::string>({ std::move(name) }), type, description)
{
}
@ -149,11 +151,45 @@ const char *core_options::entry::value() const noexcept
}
//-------------------------------------------------
// entry::value_unsubstituted
//-------------------------------------------------
const char *core_options::entry::value_unsubstituted() const noexcept
{
return value();
}
//-------------------------------------------------
// entry::copy_from
//-------------------------------------------------
void core_options::entry::copy_from(const entry &that, bool always_override)
{
// it is invalid to set the value on a header
assert(type() != option_type::HEADER);
// only set the value if we have priority
if (always_override || that.priority() >= priority())
{
if (internal_copy_value(that))
{
m_priority = that.priority();
// invoke the value changed handler, if appropriate
if (m_value_changed_handler)
m_value_changed_handler(value());
}
}
}
//-------------------------------------------------
// entry::set_value
//-------------------------------------------------
void core_options::entry::set_value(std::string &&newvalue, int priority_value, bool always_override)
void core_options::entry::set_value(std::string &&newvalue, int priority_value, bool always_override, bool perform_substitutions)
{
// it is invalid to set the value on a header
assert(type() != option_type::HEADER);
@ -163,7 +199,7 @@ void core_options::entry::set_value(std::string &&newvalue, int priority_value,
// only set the value if we have priority
if (always_override || priority_value >= priority())
{
internal_set_value(std::move(newvalue));
internal_set_value(std::move(newvalue), perform_substitutions);
m_priority = priority_value;
// invoke the value changed handler, if appropriate
@ -184,6 +220,29 @@ void core_options::entry::set_default_value(std::string &&newvalue)
}
//-------------------------------------------------
// entry::internal_copy_value
//-------------------------------------------------
bool core_options::entry::internal_copy_value(const entry &that)
{
char const *const newvalue = that.value();
if (newvalue)
{
std::string stringval = newvalue;
validate(stringval);
internal_set_value(std::move(stringval), false);
return true;
}
else
{
return false;
}
}
//-------------------------------------------------
// entry::validate
//-------------------------------------------------
@ -273,12 +332,14 @@ void core_options::entry::validate(const std::string &data)
}
break;
case core_options::option_type::STRING:
case option_type::STRING:
case option_type::PATH:
case option_type::MULTIPATH:
// strings can be anything
break;
case core_options::option_type::INVALID:
case core_options::option_type::HEADER:
case option_type::INVALID:
case option_type::HEADER:
default:
// anything else is invalid
throw options_error_exception("Attempted to set invalid option %s\n", name());
@ -337,10 +398,12 @@ const std::string &core_options::entry::default_value() const noexcept
core_options::simple_entry::simple_entry(std::vector<std::string> &&names, const char *description, core_options::option_type type, std::string &&defdata, std::string &&minimum, std::string &&maximum)
: entry(std::move(names), type, description)
, m_defdata(std::move(defdata))
, m_defdata_unsubst(std::move(defdata))
, m_minimum(std::move(minimum))
, m_maximum(std::move(maximum))
{
m_defdata = type_specific_substitutions(m_defdata_unsubst);
m_data_unsubst = m_defdata_unsubst;
m_data = m_defdata;
}
@ -366,6 +429,8 @@ const char *core_options::simple_entry::value() const noexcept
case core_options::option_type::INTEGER:
case core_options::option_type::FLOAT:
case core_options::option_type::STRING:
case core_options::option_type::PATH:
case core_options::option_type::MULTIPATH:
return m_data.c_str();
default:
@ -376,6 +441,30 @@ const char *core_options::simple_entry::value() const noexcept
}
//-------------------------------------------------
// simple_entry::value_unsubstituted
//-------------------------------------------------
const char *core_options::simple_entry::value_unsubstituted() const noexcept
{
switch (type())
{
case core_options::option_type::BOOLEAN:
case core_options::option_type::INTEGER:
case core_options::option_type::FLOAT:
case core_options::option_type::STRING:
case core_options::option_type::PATH:
case core_options::option_type::MULTIPATH:
return m_data_unsubst.c_str();
default:
// this is an option type for which returning a value is
// a meaningless operation (e.g. - core_options::option_type::COMMAND)
return nullptr;
}
}
//-------------------------------------------------
// simple_entry::default_value
//-------------------------------------------------
@ -388,12 +477,38 @@ const std::string &core_options::simple_entry::default_value() const noexcept
//-------------------------------------------------
// internal_set_value
// simple_entry::internal_set_value
//-------------------------------------------------
void core_options::simple_entry::internal_set_value(std::string &&newvalue)
void core_options::simple_entry::internal_set_value(std::string &&newvalue, bool perform_substitutions)
{
m_data = std::move(newvalue);
m_data = perform_substitutions
? type_specific_substitutions(newvalue)
: newvalue;
m_data_unsubst = std::move(newvalue);
}
//-------------------------------------------------
// simple_entry::internal_copy_value
//-------------------------------------------------
bool core_options::simple_entry::internal_copy_value(const entry &that)
{
simple_entry const *const simple = dynamic_cast<simple_entry const *>(&that);
if (!simple)
{
return entry::internal_copy_value(that);
}
else
{
validate(simple->m_data);
m_data = simple->m_data;
m_data_unsubst = simple->m_data_unsubst;
return true;
}
}
@ -403,7 +518,47 @@ void core_options::simple_entry::internal_set_value(std::string &&newvalue)
void core_options::simple_entry::set_default_value(std::string &&newvalue)
{
m_data = m_defdata = std::move(newvalue);
m_data = m_defdata = type_specific_substitutions(newvalue);
m_data_unsubst = std::move(newvalue);
}
//-------------------------------------------------
// type_specific_substitutions
//-------------------------------------------------
std::string core_options::simple_entry::type_specific_substitutions(std::string_view s) const noexcept
{
switch (type())
{
case option_type::PATH:
return osd_subst_env(s);
case option_type::MULTIPATH:
{
std::ostringstream result;
while (!s.empty())
{
std::string_view::size_type split = s.find(';');
if (std::string_view::npos == split)
split = s.length();
result << osd_subst_env(s.substr(0, split));
if (s.length() > split)
{
result << s[split];
s.remove_prefix(split + 1);
}
else
{
s.remove_prefix(split);
}
}
return std::move(result).str();
}
default:
return std::string(s);
}
}
@ -717,7 +872,7 @@ void core_options::parse_command_line(const std::vector<std::string> &args, int
}
// set the new data
do_set_value(*curentry, newdata, priority, error_stream, condition);
do_set_value(*curentry, newdata, priority, error_stream, condition, false);
}
// did we have any errors that may need to be aggregated?
@ -791,7 +946,7 @@ void core_options::parse_ini_file(util::core_file &inifile, int priority, bool i
}
// set the new data
do_set_value(*curentry, trim_spaces_and_quotes(optiondata), priority, error_stream, condition);
do_set_value(*curentry, trim_spaces_and_quotes(optiondata), priority, error_stream, condition, true);
}
// did we have any errors that may need to be aggregated?
@ -837,11 +992,7 @@ void core_options::copy_from(const core_options &that)
// identify the source entry
const entry::shared_const_ptr source_entry = that.get_entry(dest_entry->name());
if (source_entry)
{
const char *value = source_entry->value();
if (value)
dest_entry->set_value(value, source_entry->priority(), true);
}
dest_entry->copy_from(*source_entry, false);
}
}
}
@ -875,7 +1026,7 @@ std::string core_options::output_ini(const core_options *diff) const
else
{
const std::string &name(curentry->name());
const char *value(curentry->value());
const char *value(curentry->value_unsubstituted());
// check if it's unadorned
bool is_unadorned = false;
@ -889,7 +1040,7 @@ std::string core_options::output_ini(const core_options *diff) const
if (value)
{
// look up counterpart in diff, if diff is specified
if (!diff || strcmp(value, diff->value(name.c_str())))
if (!diff || strcmp(value, diff->get_entry(name.c_str())->value_unsubstituted()))
{
// output header, if we have one
if (last_header)
@ -1022,7 +1173,7 @@ void core_options::set_value(std::string_view name, std::string &&value, int pri
{
auto entry = get_entry(name);
assert(entry != nullptr);
entry->set_value(std::move(value), priority);
entry->set_value(std::move(value), priority, false, false);
}
void core_options::set_value(std::string_view name, int value, int priority)
@ -1063,13 +1214,13 @@ void core_options::remove_entry(core_options::entry &delentry)
// do_set_value
//-------------------------------------------------
void core_options::do_set_value(entry &curentry, std::string_view data, int priority, std::ostream &error_stream, condition_type &condition)
void core_options::do_set_value(entry &curentry, std::string_view data, int priority, std::ostream &error_stream, condition_type &condition, bool perform_substitutions)
{
// this is called when parsing a command line or an INI - we want to catch the option_exception and write
// any exception messages to the error stream
try
{
curentry.set_value(std::string(data), priority);
curentry.set_value(std::string(data), priority, false, perform_substitutions);
}
catch (options_warning_exception &ex)
{
@ -1156,7 +1307,7 @@ void core_options::simple_entry::revert(int priority_hi, int priority_lo)
// if our priority is within the range, revert to the default
if (priority() <= priority_hi && priority() >= priority_lo)
{
set_value(std::string(default_value()), priority(), true);
set_value(std::string(m_defdata_unsubst), priority(), true, true);
set_priority(OPTION_PRIORITY_DEFAULT);
}
}

View File

@ -104,7 +104,9 @@ public:
BOOLEAN, // boolean option
INTEGER, // integer option
FLOAT, // floating-point option
STRING // string option
STRING, // string option
PATH, // single path option
MULTIPATH // semicolon-delimited paths option
};
// information about a single entry in the options
@ -128,6 +130,7 @@ public:
const std::vector<std::string> &names() const noexcept { return m_names; }
const std::string &name() const noexcept { return m_names[0]; }
virtual const char *value() const noexcept;
virtual const char *value_unsubstituted() const noexcept;
int priority() const noexcept { return m_priority; }
void set_priority(int priority) noexcept { m_priority = priority; }
option_type type() const noexcept { return m_type; }
@ -138,18 +141,20 @@ public:
bool has_range() const noexcept;
// mutators
void set_value(std::string &&newvalue, int priority, bool always_override = false);
void copy_from(const entry &that, bool always_override);
void set_value(std::string &&newvalue, int priority, bool always_override = false, bool perform_substitutions = false);
virtual void set_default_value(std::string &&newvalue);
void set_description(const char *description) { m_description = description; }
void set_value_changed_handler(std::function<void(const char *)> &&handler) { m_value_changed_handler = std::move(handler); }
virtual void revert(int priority_hi, int priority_lo) { }
protected:
virtual void internal_set_value(std::string &&newvalue) = 0;
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) = 0;
virtual bool internal_copy_value(const entry &that);
private:
void validate(const std::string &value);
private:
const std::vector<std::string> m_names;
int m_priority;
core_options::option_type m_type;
@ -231,6 +236,7 @@ private:
// getters
virtual const char *value() const noexcept override;
virtual const char *value_unsubstituted() const noexcept override;
virtual const char *minimum() const noexcept override;
virtual const char *maximum() const noexcept override;
virtual const std::string &default_value() const noexcept override;
@ -239,14 +245,19 @@ private:
virtual void set_default_value(std::string &&newvalue) override;
protected:
virtual void internal_set_value(std::string &&newvalue) override;
virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override;
virtual bool internal_copy_value(const entry &that) override;
private:
// internal state
std::string m_data; // data for this item
std::string m_data_unsubst; // data for this item, prior to any substitution
std::string m_defdata; // default data for this item
std::string m_defdata_unsubst; // default data for this item, prior to any substitution
std::string m_minimum; // minimum value
std::string m_maximum; // maximum value
std::string type_specific_substitutions(std::string_view s) const noexcept;
};
// used internally in core_options
@ -259,7 +270,7 @@ private:
// internal helpers
void add_to_entry_map(const std::string &name, entry::shared_ptr &entry);
void do_set_value(entry &curentry, std::string_view data, int priority, std::ostream &error_stream, condition_type &condition);
void do_set_value(entry &curentry, std::string_view data, int priority, std::ostream &error_stream, condition_type &condition, bool perform_substitutions);
void throw_options_exception_if_appropriate(condition_type condition, std::ostringstream &error_stream);
// internal state

View File

@ -193,7 +193,7 @@ bool posix_directory::open_impl(std::string const &dirname)
{
assert(!m_fd);
m_path = osd_subst_env(dirname);
m_path = dirname;
m_fd.reset(::opendir(m_path.c_str()));
return bool(m_fd);
}

View File

@ -257,8 +257,6 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf
for (auto it = dst.begin(); it != dst.end(); ++it)
*it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it;
#endif
try { dst = osd_subst_env(dst); }
catch (...) { return std::errc::not_enough_memory; }
// attempt to open the file
int fd = -1;

View File

@ -161,12 +161,8 @@ DWORD create_path_recursive(TCHAR *path)
// osd_open
//============================================================
std::error_condition osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept
std::error_condition osd_file::open(std::string const &path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept
{
std::string path;
try { path = osd_subst_env(orig_path); }
catch (...) { return std::errc::not_enough_memory; }
if (win_check_socket_path(path))
return win_open_socket(path, openflags, file, filesize);
else if (win_check_ptty_path(path))

View File

@ -160,12 +160,8 @@ DWORD create_path_recursive(TCHAR *path)
// osd_open
//============================================================
osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
osd_file::error osd_file::open(std::string const &path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
{
std::string path;
try { path = osd_subst_env(orig_path); }
catch (...) { return std::errc::not_enough_memory; }
if (win_check_socket_path(path))
return win_open_socket(path, openflags, file, filesize);
else if (win_check_ptty_path(path))

View File

@ -164,13 +164,13 @@ const options_entry osd_options::s_option_entries[] =
#endif
{ nullptr, nullptr, core_options::option_type::HEADER, "BGFX POST-PROCESSING OPTIONS" },
{ OSDOPTION_BGFX_PATH, "bgfx", core_options::option_type::STRING, "path to BGFX-related files" },
{ OSDOPTION_BGFX_PATH, "bgfx", core_options::option_type::PATH, "path to BGFX-related files" },
{ OSDOPTION_BGFX_BACKEND, "auto", core_options::option_type::STRING, "BGFX backend to use (d3d9, d3d11, d3d12, metal, opengl, gles, vulkan)" },
{ OSDOPTION_BGFX_DEBUG, "0", core_options::option_type::BOOLEAN, "enable BGFX debugging statistics" },
{ OSDOPTION_BGFX_SCREEN_CHAINS, "default", core_options::option_type::STRING, "comma-delimited list of screen chain JSON names, colon-delimited per-window" },
{ OSDOPTION_BGFX_SHADOW_MASK, "slot-mask.png", core_options::option_type::STRING, "shadow mask texture name" },
{ OSDOPTION_BGFX_LUT, "lut-default.png", core_options::option_type::STRING, "LUT texture name" },
{ OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, core_options::option_type::STRING, "filename for BGFX output logging" },
{ OSDOPTION_BGFX_AVI_NAME, OSDOPTVAL_AUTO, core_options::option_type::PATH, "filename for BGFX output logging" },
// End of list
{ nullptr }

View File

@ -92,7 +92,7 @@ void chain_manager::refresh_available_chains()
m_available_chains.clear();
m_available_chains.push_back(chain_desc("none", ""));
const std::string chains_path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains", m_options.bgfx_path()));
const std::string chains_path = util::string_format("%s" PATH_SEPARATOR "chains", m_options.bgfx_path());
find_available_chains(chains_path, "");
destroy_unloaded_chains();
@ -169,7 +169,7 @@ bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index)
{
name = name + ".json";
}
std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "chains" PATH_SEPARATOR, m_options.bgfx_path()));
std::string path = util::string_format("%s" PATH_SEPARATOR "chains" PATH_SEPARATOR, m_options.bgfx_path());
path += name;
bx::FileReader reader;

View File

@ -33,7 +33,7 @@ static bool prepare_effect_document(std::string &name, osd_options &options, rap
full_name = full_name + ".json";
}
std::string path = osd_subst_env(util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path()));
std::string path = util::string_format("%s" PATH_SEPARATOR "effects" PATH_SEPARATOR, options.bgfx_path());
path += full_name;
bx::FileReader reader;

View File

@ -119,7 +119,7 @@ std::string shader_manager::make_path_string(osd_options &options, std::string n
fatalerror("Unknown BGFX renderer type %d", bgfx::getRendererType());
}
shader_path += PATH_SEPARATOR;
return osd_subst_env(shader_path);
return shader_path;
}
const bgfx::Memory* shader_manager::load_mem(std::string name)

View File

@ -77,7 +77,7 @@ int sdl_entered_debugger;
const options_entry sdl_options::s_option_entries[] =
{
{ SDLOPTION_INIPATH, INI_PATH, core_options::option_type::STRING, "path to ini files" },
{ SDLOPTION_INIPATH, INI_PATH, core_options::option_type::MULTIPATH, "path to ini files" },
// performance options
{ nullptr, nullptr, core_options::option_type::HEADER, "SDL PERFORMANCE OPTIONS" },
@ -99,7 +99,7 @@ const options_entry sdl_options::s_option_entries[] =
// keyboard mapping
{ nullptr, nullptr, core_options::option_type::HEADER, "SDL KEYBOARD MAPPING" },
{ SDLOPTION_KEYMAP, "0", core_options::option_type::BOOLEAN, "enable keymap" },
{ SDLOPTION_KEYMAP_FILE, "keymap.dat", core_options::option_type::STRING, "keymap filename" },
{ SDLOPTION_KEYMAP_FILE, "keymap.dat", core_options::option_type::PATH, "keymap filename" },
// joystick mapping
{ nullptr, nullptr, core_options::option_type::HEADER, "SDL JOYSTICK MAPPING" },

View File

@ -176,10 +176,10 @@ const options_entry windows_options::s_option_entries[] =
// post-processing options
{ nullptr, nullptr, core_options::option_type::HEADER, "DIRECT3D POST-PROCESSING OPTIONS" },
{ WINOPTION_HLSLPATH, "hlsl", core_options::option_type::STRING, "path to HLSL support files" },
{ WINOPTION_HLSLPATH, "hlsl", core_options::option_type::PATH, "path to HLSL support files" },
{ WINOPTION_HLSL_ENABLE";hlsl", "0", core_options::option_type::BOOLEAN, "enable HLSL post-processing (PS3.0 required)" },
{ WINOPTION_HLSL_OVERSAMPLING, "0", core_options::option_type::BOOLEAN, "enable HLSL oversampling" },
{ WINOPTION_HLSL_WRITE, OSDOPTVAL_AUTO, core_options::option_type::STRING, "enable HLSL AVI writing (huge disk bandwidth suggested)" },
{ WINOPTION_HLSL_WRITE, OSDOPTVAL_AUTO, core_options::option_type::PATH, "enable HLSL AVI writing (huge disk bandwidth suggested)" },
{ WINOPTION_HLSL_SNAP_WIDTH, "2048", core_options::option_type::STRING, "HLSL upscaled-snapshot width" },
{ WINOPTION_HLSL_SNAP_HEIGHT, "1536", core_options::option_type::STRING, "HLSL upscaled-snapshot height" },
{ WINOPTION_SHADOW_MASK_TILE_MODE, "0", core_options::option_type::INTEGER, "shadow mask tile mode (0 for screen based, 1 for source based)" },
@ -262,9 +262,9 @@ const options_entry windows_options::s_option_entries[] =
{ WINOPTION_BLOOM_LEVEL6_WEIGHT, "0.04", core_options::option_type::FLOAT, "bloom level 6 weight (1/4 smaller that level 5 target)" },
{ WINOPTION_BLOOM_LEVEL7_WEIGHT, "0.02", core_options::option_type::FLOAT, "bloom level 7 weight (1/4 smaller that level 6 target)" },
{ WINOPTION_BLOOM_LEVEL8_WEIGHT, "0.01", core_options::option_type::FLOAT, "bloom level 8 weight (1/4 smaller that level 7 target)" },
{ WINOPTION_LUT_TEXTURE, "lut-default.png", core_options::option_type::STRING, "3D LUT texture filename for screen, PNG format" },
{ WINOPTION_LUT_TEXTURE, "lut-default.png", core_options::option_type::PATH, "3D LUT texture filename for screen, PNG format" },
{ WINOPTION_LUT_ENABLE, "0", core_options::option_type::BOOLEAN, "Enables 3D LUT to be applied to screen after post-processing" },
{ WINOPTION_UI_LUT_TEXTURE, "lut-default.png", core_options::option_type::STRING, "3D LUT texture filename of UI, PNG format" },
{ WINOPTION_UI_LUT_TEXTURE, "lut-default.png", core_options::option_type::PATH, "3D LUT texture filename of UI, PNG format" },
{ WINOPTION_UI_LUT_ENABLE, "0", core_options::option_type::BOOLEAN, "enable 3D LUT to be applied to UI and artwork after post-processing" },
// full screen options