// For licensing and usage information, read docs/release/winui_license.txt // MASTER //**************************************************************************** /*************************************************************************** emu_opts.cpp Interface to MAME's options and ini files. ***************************************************************************/ // standard windows headers #include #include // standard C headers #include // MAME/MAMEUI headers #include "emu.h" #include "winmain.h" #include "ui/moptions.h" #include "drivenum.h" #include "emu_opts.h" static emu_options mameopts; // core options static ui_options emu_ui; // ui.ini static windows_options emu_global; // Global 'default' options #define UI_FILENAME "ini\\ui.ini" typedef std::string string; // char names void emu_set_value(windows_options *o, const char* name, float value) { std::ostringstream ss; ss << value; string svalue(ss.str()); string sname = string(name); o->set_value(sname, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options *o, const char* name, int value) { string svalue = std::to_string(value); string sname = string(name); o->set_value(sname, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options *o, const char* name, string value) { string sname = string(name); o->set_value(sname, value, OPTION_PRIORITY_CMDLINE); } // string names void emu_set_value(windows_options *o, string name, float value) { std::ostringstream ss; ss << value; string svalue(ss.str()); o->set_value(name, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options *o, string name, int value) { string svalue = std::to_string(value); o->set_value(name, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options *o, string name, string value) { o->set_value(name, value, OPTION_PRIORITY_CMDLINE); } // char names void emu_set_value(windows_options &o, const char* name, float value) { std::ostringstream ss; ss << value; string svalue(ss.str()); string sname = string(name); o.set_value(sname, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options &o, const char* name, int value) { string svalue = std::to_string(value); string sname = string(name); o.set_value(sname, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options &o, const char* name, string value) { string sname = string(name); o.set_value(sname, value, OPTION_PRIORITY_CMDLINE); } // string names void emu_set_value(windows_options &o, string name, float value) { std::ostringstream ss; ss << value; string svalue(ss.str()); o.set_value(name, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options &o, string name, int value) { string svalue = std::to_string(value); o.set_value(name, svalue, OPTION_PRIORITY_CMDLINE); } void emu_set_value(windows_options &o, string name, string value) { o.set_value(name, value, OPTION_PRIORITY_CMDLINE); } void ui_set_value(ui_options &o, string name, string value) { o.set_value(name, value, OPTION_PRIORITY_CMDLINE); } string emu_get_value(windows_options *o, string name) { const char* t = o->value(name.c_str()); if (t) return string(o->value(name.c_str())); else return ""; } string emu_get_value(windows_options &o, string name) { const char* t = o.value(name.c_str()); if (t) return string(o.value(name.c_str())); else return ""; } string ui_get_value(ui_options &o, string name) { const char* t = o.value(name.c_str()); if (t) return string(o.value(name.c_str())); else return ""; } struct dir_data { string dir_path; int which; }; static std::map dir_map; static string emu_path; string GetIniDir(void) { /// const char *ini_dir; // const char *s; // ini_dir = global.value(OPTION_INIPATH); // while((s = strchr(ini_dir, ';')) != NULL) // { // ini_dir = s + 1; // } /// ini_dir = "ini\0"; /// return ini_dir; return emu_path + "ini\0"; } // load mewui settings static void LoadSettingsFile(ui_options &opts, const char *filename) { util::core_file::ptr file; std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ, file); if (!filerr) { opts.parse_ini_file(*file, OPTION_PRIORITY_CMDLINE, true, true); file.reset(); } } // load a game ini static void LoadSettingsFile(windows_options &opts, const char *filename) { util::core_file::ptr file; std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ, file); if (!filerr) { opts.parse_ini_file(*file, OPTION_PRIORITY_CMDLINE, true, true); file.reset(); } } // This saves changes to .INI or MAME.INI only static void SaveSettingsFile(windows_options &opts, const char *filename) { util::core_file::ptr file; std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, file); if (!filerr) { string inistring = opts.output_ini(); // printf("=====%s=====\n%s\n",filename,inistring.c_str()); // for debugging file->puts(inistring.c_str()); file.reset(); } } /* get options, based on passed in game number. */ void load_options(windows_options &opts, OPTIONS_TYPE opt_type, int game_num, bool set_system_name) { const game_driver *driver = NULL; if (game_num > -1) driver = &driver_list::driver(game_num); // Try base ini first string fname = string(emulator_info::get_configname()).append(".ini"); LoadSettingsFile(opts, fname.c_str()); if (opt_type == OPTIONS_SOURCE) { fname = GetIniDir() + PATH_SEPARATOR + "source" + PATH_SEPARATOR + string(core_filename_extract_base(driver->type.source(), true)) + ".ini"; LoadSettingsFile(opts, fname.c_str()); return; } fname.clear(); if (opt_type == OPTIONS_ARCADE) fname = GetIniDir() + PATH_SEPARATOR + "arcade.ini"; else if (opt_type == OPTIONS_HORIZONTAL) fname = GetIniDir() + PATH_SEPARATOR + "horizontal.ini"; else if (opt_type == OPTIONS_RASTER) fname = GetIniDir() + PATH_SEPARATOR + "raster.ini"; else if (opt_type == OPTIONS_VECTOR) fname = GetIniDir() + PATH_SEPARATOR + "vector.ini"; else if (opt_type == OPTIONS_VERTICAL) fname = GetIniDir() + PATH_SEPARATOR + "vertical.ini"; if (!fname.empty()) { LoadSettingsFile(opts, fname.c_str()); return; } if (game_num > -2) { // Now try global ini fname = GetIniDir() + PATH_SEPARATOR + string(emulator_info::get_configname()).append(".ini"); LoadSettingsFile(opts, fname.c_str()); if (game_num > -1) { // Lastly, gamename.ini if (driver) { fname = GetIniDir() + PATH_SEPARATOR + string(driver->name).append(".ini"); if (set_system_name) opts.set_value(OPTION_SYSTEMNAME, driver->name, OPTION_PRIORITY_CMDLINE); LoadSettingsFile(opts, fname.c_str()); } } } if (game_num > -1) SetDirectories(opts); } /* Save ini file based on game_number. */ void save_options(windows_options &opts, OPTIONS_TYPE opt_type, int game_num) { const game_driver *driver = NULL; string fname, filepath; if (opt_type == OPTIONS_ARCADE) fname = GetIniDir() + PATH_SEPARATOR + "arcade.ini"; else if (opt_type == OPTIONS_HORIZONTAL) fname = GetIniDir() + PATH_SEPARATOR + "horizontal.ini"; else if (opt_type == OPTIONS_RASTER) fname = GetIniDir() + PATH_SEPARATOR + "raster.ini"; else if (opt_type == OPTIONS_VECTOR) fname = GetIniDir() + PATH_SEPARATOR + "vector.ini"; else if (opt_type == OPTIONS_VERTICAL) fname = GetIniDir() + PATH_SEPARATOR + "vertical.ini"; if (!fname.empty()) { SaveSettingsFile(opts, fname.c_str()); return; } if (game_num >= 0) { driver = &driver_list::driver(game_num); if (driver) { fname.assign(driver->name); if (opt_type == OPTIONS_SOURCE) filepath = GetIniDir() + PATH_SEPARATOR + "source" + PATH_SEPARATOR + string(core_filename_extract_base(driver->type.source(), true)) + ".ini"; } } else if (game_num == -1) fname = string(emulator_info::get_configname()); if (!fname.empty() && filepath.empty()) filepath = GetIniDir().append(PATH_SEPARATOR).append(fname.c_str()).append(".ini"); if (game_num == -2) filepath = string(emulator_info::get_configname()).append(".ini"); if (!filepath.empty()) { if (game_num > -1) SetDirectories(opts); SaveSettingsFile(opts, filepath.c_str()); // printf("Settings saved to %s\n",filepath.c_str()); } // else // printf("Unable to save settings\n"); } void emu_opts_init(bool b) { printf("emuOptsInit: About to load %s\n",UI_FILENAME);fflush(stdout); LoadSettingsFile(emu_ui, UI_FILENAME); // parse UI.INI printf("emuOptsInit: About to load Global Options\n");fflush(stdout); load_options(emu_global, OPTIONS_GLOBAL, -1, 0); // parse MAME.INI printf("emuOptsInit: Finished\n");fflush(stdout); if (b) return; char exe_path[MAX_PATH]; GetModuleFileNameA(nullptr, exe_path, MAX_PATH); emu_path = string(exe_path); std::size_t pos = emu_path.find_last_of("\\"); emu_path = emu_path.substr(0,++pos); emu_path.resize(pos); printf("%s\n",emu_path.c_str()); dir_map[1] = dir_data { OPTION_PLUGINDATAPATH, 0 }; dir_map[2] = dir_data { OPTION_MEDIAPATH, 0 }; dir_map[3] = dir_data { OPTION_HASHPATH, 0 }; dir_map[4] = dir_data { OPTION_SAMPLEPATH, 0 }; dir_map[5] = dir_data { OPTION_ARTPATH, 0 }; dir_map[6] = dir_data { OPTION_CTRLRPATH, 0 }; dir_map[7] = dir_data { OPTION_INIPATH, 0 }; dir_map[8] = dir_data { OPTION_FONTPATH, 0 }; dir_map[9] = dir_data { OPTION_CHEATPATH, 0 }; dir_map[10] = dir_data { OPTION_CROSSHAIRPATH, 0 }; dir_map[11] = dir_data { OPTION_PLUGINSPATH, 0 }; dir_map[12] = dir_data { OPTION_LANGUAGEPATH, 0 }; dir_map[13] = dir_data { OPTION_SWPATH, 0 }; dir_map[14] = dir_data { OPTION_CFG_DIRECTORY, 0 }; dir_map[15] = dir_data { OPTION_NVRAM_DIRECTORY, 0 }; dir_map[16] = dir_data { OPTION_INPUT_DIRECTORY, 0 }; dir_map[17] = dir_data { OPTION_STATE_DIRECTORY, 0 }; dir_map[18] = dir_data { OPTION_SNAPSHOT_DIRECTORY, 0 }; dir_map[19] = dir_data { OPTION_DIFF_DIRECTORY, 0 }; dir_map[20] = dir_data { OPTION_COMMENT_DIRECTORY, 0 }; dir_map[21] = dir_data { OSDOPTION_BGFX_PATH, 0 }; dir_map[22] = dir_data { WINOPTION_HLSLPATH, 0 }; dir_map[23] = dir_data { OPTION_HISTORY_PATH, 1 }; dir_map[24] = dir_data { OPTION_CATEGORYINI_PATH, 1 }; dir_map[25] = dir_data { OPTION_CABINETS_PATH, 1 }; dir_map[26] = dir_data { OPTION_CPANELS_PATH, 1 }; dir_map[27] = dir_data { OPTION_PCBS_PATH, 1 }; dir_map[28] = dir_data { OPTION_FLYERS_PATH, 1 }; dir_map[29] = dir_data { OPTION_TITLES_PATH, 1 }; dir_map[30] = dir_data { OPTION_ENDS_PATH, 1 }; dir_map[31] = dir_data { OPTION_MARQUEES_PATH, 1 }; dir_map[32] = dir_data { OPTION_ARTPREV_PATH, 1 }; dir_map[33] = dir_data { OPTION_BOSSES_PATH, 1 }; dir_map[34] = dir_data { OPTION_LOGOS_PATH, 1 }; dir_map[35] = dir_data { OPTION_SCORES_PATH, 1 }; dir_map[36] = dir_data { OPTION_VERSUS_PATH, 1 }; dir_map[37] = dir_data { OPTION_GAMEOVER_PATH, 1 }; dir_map[38] = dir_data { OPTION_HOWTO_PATH, 1 }; dir_map[39] = dir_data { OPTION_SELECT_PATH, 1 }; dir_map[40] = dir_data { OPTION_ICONS_PATH, 1 }; dir_map[41] = dir_data { OPTION_COVER_PATH, 1 }; dir_map[42] = dir_data { OPTION_UI_PATH, 1 }; } void dir_set_value(int dir_index, string value) { if (dir_index) { if (dir_map.count(dir_index) > 0) { string sname = dir_map[dir_index].dir_path; int which = dir_map[dir_index].which; if (which) ui_set_value(emu_ui, sname, value); else emu_set_value(emu_global, sname, value); } } } string dir_get_value(int dir_index) { if (dir_index) { if (dir_map.count(dir_index) > 0) { string sname = dir_map[dir_index].dir_path; int which = dir_map[dir_index].which; if (which) return ui_get_value(emu_ui, sname); else return emu_get_value(emu_global, sname); } } return ""; } // This saves changes to UI.INI only static void SaveSettingsFile(ui_options &opts, const char *filename) { util::core_file::ptr file; std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, file); if (!filerr) { string inistring = opts.output_ini(); file->puts(inistring.c_str()); file.reset(); } } void ui_save_ini() { SaveSettingsFile(emu_ui, UI_FILENAME); } void SetDirectories(windows_options &o) { emu_set_value(o, OPTION_MEDIAPATH, dir_get_value(2)); emu_set_value(o, OPTION_SAMPLEPATH, dir_get_value(4)); emu_set_value(o, OPTION_INIPATH, dir_get_value(7)); emu_set_value(o, OPTION_CFG_DIRECTORY, dir_get_value(14)); emu_set_value(o, OPTION_SNAPSHOT_DIRECTORY, dir_get_value(18)); emu_set_value(o, OPTION_INPUT_DIRECTORY, dir_get_value(16)); emu_set_value(o, OPTION_STATE_DIRECTORY, dir_get_value(17)); emu_set_value(o, OPTION_ARTPATH, dir_get_value(5)); emu_set_value(o, OPTION_NVRAM_DIRECTORY, dir_get_value(15)); emu_set_value(o, OPTION_CTRLRPATH, dir_get_value(6)); emu_set_value(o, OPTION_CHEATPATH, dir_get_value(9)); emu_set_value(o, OPTION_CROSSHAIRPATH, dir_get_value(10)); emu_set_value(o, OPTION_FONTPATH, dir_get_value(8)); emu_set_value(o, OPTION_DIFF_DIRECTORY, dir_get_value(19)); emu_set_value(o, OPTION_SNAPNAME, emu_get_value(emu_global, OPTION_SNAPNAME)); emu_set_value(o, OPTION_DEBUG, "0"); emu_set_value(o, OPTION_SPEAKER_REPORT, "0"); emu_set_value(o, OPTION_VERBOSE, "0"); emu_set_value(o, OPTION_LOG, "0"); emu_set_value(o, OPTION_OSLOG, "0"); } // For dialogs.cpp const char* GetSnapName(void) { return emu_global.value(OPTION_SNAPNAME); } void SetSnapName(const char* value) { string nvalue = value ? string(value) : ""; emu_set_value(emu_global, OPTION_SNAPNAME, nvalue); global_save_ini(); } // For winui.cpp const string GetLanguageUI(void) { return emu_global.value(OPTION_LANGUAGE); } bool GetEnablePlugins(void) { return emu_global.bool_value(OPTION_PLUGINS); } const string GetPlugins(void) { return emu_global.value(OPTION_PLUGIN); } bool GetSkipWarnings(void) { return emu_ui.bool_value(OPTION_SKIP_WARNINGS); } void SetSkipWarnings(BOOL val) { string c = val ? "1" : "0"; ui_set_value(emu_ui, OPTION_SKIP_WARNINGS, c); } void SetSelectedSoftware(int driver_index, string opt_name, const char *software) { if (opt_name.empty()) { // Software List Item, we write to SOFTWARENAME to ensure all parts of a multipart set are loaded windows_options o; printf("About to write %s to OPTION_SOFTWARENAME\n",software);fflush(stdout); load_options(o, OPTIONS_GAME, driver_index, 1); o.set_value(OPTION_SOFTWARENAME, software, OPTION_PRIORITY_CMDLINE); save_options(o, OPTIONS_GAME, driver_index); } else { // Loose software, we write the filename to the requested image device const char *s = opt_name.c_str(); printf("SetSelectedSoftware(): slot=%s driver=%s software='%s'\n", s, driver_list::driver(driver_index).name, software); printf("About to load %s into slot %s\n",software,s);fflush(stdout); windows_options o; load_options(o, OPTIONS_GAME, driver_index, 1); o.set_value(s, software, OPTION_PRIORITY_CMDLINE); //o.image_option(opt_name).specify(software); printf("Done\n");;fflush(stdout); save_options(o, OPTIONS_GAME, driver_index); } } // See if this driver has software support bool DriverHasSoftware(uint32_t drvindex) { if (drvindex < driver_list::total()) { windows_options o; load_options(o, OPTIONS_GAME, drvindex, 1); machine_config config(driver_list::driver(drvindex), o); for (device_image_interface &img : image_interface_enumerator(config.root_device())) if (img.user_loadable()) return 1; } return 0; } void global_save_ini(void) { string fname = GetIniDir() + PATH_SEPARATOR + string(emulator_info::get_configname()).append(".ini"); SaveSettingsFile(emu_global, fname.c_str()); } bool AreOptionsEqual(windows_options &opts1, windows_options &opts2) { for (auto &curentry : opts1.entries()) { if (curentry->type() != core_options::option_type::HEADER) { const char *value = curentry->value(); const char *comp = opts2.value(curentry->name().c_str()); if (!value && !comp) // both empty, they are the same {} else if (!value || !comp) // only one empty, they are different return false; else if (strcmp(value, comp) != 0) // both not empty, do proper compare return false; } } return true; } void OptionsCopy(windows_options &source, windows_options &dest) { for (auto &dest_entry : source.entries()) { if (dest_entry->names().size() > 0) { // identify the source entry const core_options::entry::shared_ptr source_entry = source.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); } } } } // Reset the given windows_options to their default settings. static void ResetToDefaults(windows_options &opts, int priority) { // iterate through the options setting each one back to the default value. windows_options dummy; OptionsCopy(dummy, opts); } void ResetGameOptions(int driver_index) { //save_options(NULL, OPTIONS_GAME, driver_index); } void ResetGameDefaults(void) { // Walk the global settings and reset everything to defaults; ResetToDefaults(emu_global, OPTION_PRIORITY_CMDLINE); save_options(emu_global, OPTIONS_GLOBAL, GLOBAL_OPTIONS); } /* * Reset all game, vector and source options to defaults. * No reason to reboot if this is done. */ void ResetAllGameOptions(void) { for (int i = 0; i < driver_list::total(); i++) ResetGameOptions(i); } windows_options & MameUIGlobal(void) { return emu_global; } void SetSystemName(windows_options &opts, OPTIONS_TYPE opt_type, int driver_index) { if (driver_index >= 0) mameopts.set_system_name(driver_list::driver(driver_index).name); }