mirror of https://github.com/stella-emu/stella.git
681 lines
25 KiB
C++
681 lines
25 KiB
C++
//============================================================================
|
|
//
|
|
// SSSS tt lll lll
|
|
// SS SS tt ll ll
|
|
// SS tttttt eeee ll ll aaaa
|
|
// SSSS tt ee ee ll ll aa
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
// SS SS tt ee ll ll aa aa
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
//
|
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
// and the Stella Team
|
|
//
|
|
// See the file "License.txt" for information on usage and redistribution of
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
//============================================================================
|
|
|
|
#include <cassert>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <algorithm>
|
|
|
|
#include "bspf.hxx"
|
|
|
|
#include "OSystem.hxx"
|
|
#include "Version.hxx"
|
|
|
|
#ifdef DEBUGGER_SUPPORT
|
|
#include "DebuggerDialog.hxx"
|
|
#endif
|
|
|
|
#include "Settings.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Settings::Settings(OSystem& osystem)
|
|
: myOSystem(osystem)
|
|
{
|
|
// Video-related options
|
|
setInternal("video", "");
|
|
setInternal("vsync", "true");
|
|
setInternal("fullscreen", "false");
|
|
setInternal("center", "false");
|
|
setInternal("palette", "standard");
|
|
setInternal("colorloss", "false");
|
|
setInternal("timing", "sleep");
|
|
setInternal("uimessages", "true");
|
|
|
|
// TIA specific options
|
|
setInternal("tia.zoom", "3");
|
|
setInternal("tia.inter", "false");
|
|
setInternal("tia.aspectn", "90");
|
|
setInternal("tia.aspectp", "100");
|
|
setInternal("tia.fsfill", "false");
|
|
setInternal("tia.dbgcolors", "roygpb");
|
|
|
|
// TV filtering options
|
|
setInternal("tv.filter", "0");
|
|
setInternal("tv.phosphor", "50");
|
|
setInternal("tv.jitter", "true");
|
|
setInternal("tv.jitter_recovery", "10");
|
|
setInternal("tv.scanlines", "25");
|
|
setInternal("tv.scaninter", "true");
|
|
// TV options when using 'custom' mode
|
|
setInternal("tv.contrast", "0.0");
|
|
setInternal("tv.brightness", "0.0");
|
|
setInternal("tv.hue", "0.0");
|
|
setInternal("tv.saturation", "0.0");
|
|
setInternal("tv.gamma", "0.0");
|
|
setInternal("tv.sharpness", "0.0");
|
|
setInternal("tv.resolution", "0.0");
|
|
setInternal("tv.artifacts", "0.0");
|
|
setInternal("tv.fringing", "0.0");
|
|
setInternal("tv.bleed", "0.0");
|
|
|
|
// Sound options
|
|
setInternal("sound", "true");
|
|
setInternal("fragsize", "512");
|
|
setInternal("freq", "31400");
|
|
setInternal("volume", "100");
|
|
|
|
// Input event options
|
|
setInternal("keymap", "");
|
|
setInternal("joymap", "");
|
|
setInternal("combomap", "");
|
|
setInternal("joydeadzone", "13");
|
|
setInternal("joyallow4", "false");
|
|
setInternal("usemouse", "analog");
|
|
setInternal("grabmouse", "true");
|
|
setInternal("cursor", "2");
|
|
setInternal("dsense", "10");
|
|
setInternal("msense", "10");
|
|
setInternal("saport", "lr");
|
|
setInternal("ctrlcombo", "true");
|
|
|
|
// Snapshot options
|
|
setInternal("snapsavedir", "");
|
|
setInternal("snaploaddir", "");
|
|
setInternal("snapname", "int");
|
|
setInternal("sssingle", "false");
|
|
setInternal("ss1x", "false");
|
|
setInternal("ssinterval", "2");
|
|
|
|
// Config files and paths
|
|
setInternal("romdir", "");
|
|
setInternal("statedir", "");
|
|
setInternal("cheatfile", "");
|
|
setInternal("palettefile", "");
|
|
setInternal("propsfile", "");
|
|
setInternal("nvramdir", "");
|
|
setInternal("cfgdir", "");
|
|
|
|
// ROM browser options
|
|
setInternal("exitlauncher", "false");
|
|
setInternal("launcherres", GUI::Size(900, 600));
|
|
setInternal("launcherfont", "medium");
|
|
setInternal("launcherexts", "allroms");
|
|
setInternal("romviewer", "1");
|
|
setInternal("lastrom", "");
|
|
|
|
// UI-related options
|
|
#ifdef DEBUGGER_SUPPORT
|
|
setInternal("dbg.res",
|
|
GUI::Size(DebuggerDialog::kMediumFontMinW,
|
|
DebuggerDialog::kMediumFontMinH));
|
|
#endif
|
|
setInternal("uipalette", "standard");
|
|
setInternal("listdelay", "300");
|
|
setInternal("mwheel", "4");
|
|
|
|
// Misc options
|
|
setInternal("autoslot", "false");
|
|
setInternal("loglevel", "1");
|
|
setInternal("logtoconsole", "0");
|
|
setInternal("tiadriven", "false");
|
|
setInternal("cpurandom", "");
|
|
setInternal("ramrandom", "true");
|
|
setInternal("avoxport", "");
|
|
setInternal("stats", "false");
|
|
setInternal("fastscbios", "true");
|
|
setExternal("romloadcount", "0");
|
|
setExternal("maxres", "");
|
|
|
|
#ifdef DEBUGGER_SUPPORT
|
|
// Debugger/disassembly options
|
|
setInternal("dbg.fontstyle", "0");
|
|
setInternal("dbg.uhex", "true");
|
|
setInternal("dis.resolve", "true");
|
|
setInternal("dis.gfxformat", "2");
|
|
setInternal("dis.showaddr", "true");
|
|
setInternal("dis.relocate", "false");
|
|
#endif
|
|
|
|
#ifdef DTHUMB_SUPPORT
|
|
// Thumb ARM emulation options
|
|
setInternal("thumb.trapfatal", "true");
|
|
#endif
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Settings::loadConfig()
|
|
{
|
|
string line, key, value;
|
|
string::size_type equalPos, garbage;
|
|
|
|
ifstream in(myOSystem.configFile());
|
|
if(!in || !in.is_open())
|
|
{
|
|
myOSystem.logMessage("ERROR: Couldn't load settings file", 0);
|
|
return;
|
|
}
|
|
|
|
while(getline(in, line))
|
|
{
|
|
// Strip all whitespace and tabs from the line
|
|
while((garbage = line.find("\t")) != string::npos)
|
|
line.erase(garbage, 1);
|
|
|
|
// Ignore commented and empty lines
|
|
if((line.length() == 0) || (line[0] == ';'))
|
|
continue;
|
|
|
|
// Search for the equal sign and discard the line if its not found
|
|
if((equalPos = line.find("=")) == string::npos)
|
|
continue;
|
|
|
|
// Split the line into key/value pairs and trim any whitespace
|
|
key = line.substr(0, equalPos);
|
|
value = line.substr(equalPos + 1, line.length() - key.length() - 1);
|
|
key = trim(key);
|
|
value = trim(value);
|
|
|
|
// Check for absent key or value
|
|
if((key.length() == 0) || (value.length() == 0))
|
|
continue;
|
|
|
|
// Only settings which have been previously set are valid
|
|
if(int idx = getInternalPos(key) != -1)
|
|
setInternal(key, value, idx, true);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
string Settings::loadCommandLine(int argc, char** argv)
|
|
{
|
|
for(int i = 1; i < argc; ++i)
|
|
{
|
|
// strip off the '-' character
|
|
string key = argv[i];
|
|
if(key[0] == '-')
|
|
{
|
|
key = key.substr(1, key.length());
|
|
|
|
// Take care of the arguments which are meant to be executed immediately
|
|
// (and then Stella should exit)
|
|
if(key == "help" || key == "listrominfo")
|
|
{
|
|
setExternal(key, "true");
|
|
return "";
|
|
}
|
|
|
|
// Take care of arguments without an option or ones that shouldn't
|
|
// be saved to the config file
|
|
if(key == "rominfo" || key == "debug" || key == "holdreset" ||
|
|
key == "holdselect" || key == "takesnapshot")
|
|
{
|
|
setExternal(key, "true");
|
|
continue;
|
|
}
|
|
|
|
ostringstream buf;
|
|
if(++i >= argc)
|
|
{
|
|
buf << "Missing argument for '" << key << "'" << endl;
|
|
myOSystem.logMessage(buf.str(), 0);
|
|
return "";
|
|
}
|
|
string value = argv[i];
|
|
|
|
buf.str("");
|
|
buf << " key = '" << key << "', value = '" << value << "'";
|
|
|
|
// Settings read from the commandline must not be saved to
|
|
// the rc-file, unless they were previously set
|
|
if(int idx = getInternalPos(key) != -1)
|
|
{
|
|
setInternal(key, value, idx); // don't set initialValue here
|
|
buf << "(I)\n";
|
|
}
|
|
else
|
|
{
|
|
setExternal(key, value);
|
|
buf << "(E)\n";
|
|
}
|
|
|
|
myOSystem.logMessage(buf.str(), 2);
|
|
}
|
|
else
|
|
return key;
|
|
}
|
|
|
|
return EmptyString;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Settings::validate()
|
|
{
|
|
string s;
|
|
int i;
|
|
|
|
s = getString("timing");
|
|
if(s != "sleep" && s != "busy") setInternal("timing", "sleep");
|
|
|
|
i = getInt("tia.aspectn");
|
|
if(i < 80 || i > 120) setInternal("tia.aspectn", "90");
|
|
i = getInt("tia.aspectp");
|
|
if(i < 80 || i > 120) setInternal("tia.aspectp", "100");
|
|
|
|
s = getString("tia.dbgcolors");
|
|
sort(s.begin(), s.end());
|
|
if(s != "bgopry") setInternal("tia.dbgcolors", "roygpb");
|
|
|
|
i = getInt("tv.phosphor");
|
|
if(i < 0 || i > 100) setInternal("tv.phosphor", "50");
|
|
|
|
i = getInt("tv.filter");
|
|
if(i < 0 || i > 5) setInternal("tv.filter", "0");
|
|
|
|
i = getInt("tv.jitter_recovery");
|
|
if(i < 1 || i > 20) setInternal("tv.jitter_recovery", "10");
|
|
|
|
#ifdef SOUND_SUPPORT
|
|
i = getInt("volume");
|
|
if(i < 0 || i > 100) setInternal("volume", "100");
|
|
i = getInt("freq");
|
|
if(!(i == 11025 || i == 22050 || i == 31400 || i == 44100 || i == 48000))
|
|
setInternal("freq", "31400");
|
|
#endif
|
|
|
|
i = getInt("joydeadzone");
|
|
if(i < 0) setInternal("joydeadzone", "0");
|
|
else if(i > 29) setInternal("joydeadzone", "29");
|
|
|
|
i = getInt("cursor");
|
|
if(i < 0 || i > 3)
|
|
setInternal("cursor", "2");
|
|
|
|
i = getInt("dsense");
|
|
if(i < 1) setInternal("dsense", "1");
|
|
else if(i > 20) setInternal("dsense", "10");
|
|
|
|
i = getInt("msense");
|
|
if(i < 1) setInternal("msense", "1");
|
|
else if(i > 20) setInternal("msense", "15");
|
|
|
|
i = getInt("ssinterval");
|
|
if(i < 1) setInternal("ssinterval", "2");
|
|
else if(i > 10) setInternal("ssinterval", "10");
|
|
|
|
s = getString("palette");
|
|
if(s != "standard" && s != "z26" && s != "user")
|
|
setInternal("palette", "standard");
|
|
|
|
s = getString("launcherfont");
|
|
if(s != "small" && s != "medium" && s != "large")
|
|
setInternal("launcherfont", "medium");
|
|
|
|
i = getInt("romviewer");
|
|
if(i < 0) setInternal("romviewer", "0");
|
|
else if(i > 2) setInternal("romviewer", "2");
|
|
|
|
i = getInt("loglevel");
|
|
if(i < 0 || i > 2)
|
|
setInternal("loglevel", "1");
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Settings::usage() const
|
|
{
|
|
cout << endl
|
|
<< "Stella version " << STELLA_VERSION << endl
|
|
<< endl
|
|
<< "Usage: stella [options ...] romfile" << endl
|
|
<< " Run without any options or romfile to use the ROM launcher" << endl
|
|
<< " Consult the manual for more in-depth information" << endl
|
|
<< endl
|
|
<< "Valid options are:" << endl
|
|
<< endl
|
|
<< " -video <type> Type is one of the following:\n"
|
|
#ifdef BSPF_WINDOWS
|
|
<< " direct3d Direct3D acceleration\n"
|
|
#endif
|
|
<< " opengl OpenGL acceleration\n"
|
|
<< " opengles2 OpenGLES 2 acceleration\n"
|
|
<< " opengles OpenGLES 1 acceleration\n"
|
|
<< " software Software mode (no acceleration)\n"
|
|
<< endl
|
|
<< " -vsync <1|0> Enable 'synchronize to vertical blank interrupt'\n"
|
|
<< " -fullscreen <1|0> Enable fullscreen mode\n"
|
|
<< " -center <1|0> Centers game window (if possible)\n"
|
|
<< " -palette <standard| Use the specified color palette\n"
|
|
<< " z26|\n"
|
|
<< " user>\n"
|
|
<< " -colorloss <1|0> Enable PAL color-loss effect\n"
|
|
<< " -framerate <number> Display the given number of frames per second (0 to auto-calculate)\n"
|
|
<< " -timing <sleep|busy> Use the given type of wait between frames\n"
|
|
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
|
|
<< endl
|
|
#ifdef SOUND_SUPPORT
|
|
<< " -sound <1|0> Enable sound generation\n"
|
|
<< " -fragsize <number> The size of sound fragments (must be a power of two)\n"
|
|
<< " -freq <number> Set sound sample output frequency (11025|22050|31400|44100|48000)\n"
|
|
<< " -volume <number> Set the volume (0 - 100)\n"
|
|
<< endl
|
|
#endif
|
|
<< " -tia.zoom <zoom> Use the specified zoom level (windowed mode) for TIA image\n"
|
|
<< " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA image\n"
|
|
<< " -tia.aspectn <number> Scale TIA width by the given percentage in NTSC mode\n"
|
|
<< " -tia.aspectp <number> Scale TIA width by the given percentage in PAL mode\n"
|
|
<< " -tia.fsfill <1|0> Stretch TIA image to fill fullscreen mode\n"
|
|
<< " -tia.dbgcolors <string> Debug colors to use for each object (see manual for description)\n"
|
|
<< endl
|
|
<< " -tv.filter <0-5> Set TV effects off (0) or to specified mode (1-5)\n"
|
|
<< " -tv.phosphor <0-100> Set default blend level in phosphor mode\n"
|
|
<< " -tv.jitter <1|0> Enable TV jitter effect\n"
|
|
<< " -tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
|
|
<< " -tv.scanlines <0-100> Set scanline intensity to percentage (0 disables completely)\n"
|
|
<< " -tv.scaninter <1|0> Enable interpolated (smooth) scanlines\n"
|
|
<< " -tv.contrast <value> Set TV effects custom contrast to value 1.0 - 1.0\n"
|
|
<< " -tv.brightness <value> Set TV effects custom brightness to value 1.0 - 1.0\n"
|
|
<< " -tv.hue <value> Set TV effects custom hue to value 1.0 - 1.0\n"
|
|
<< " -tv.saturation <value> Set TV effects custom saturation to value 1.0 - 1.0\n"
|
|
<< " -tv.gamma <value> Set TV effects custom gamma to value 1.0 - 1.0\n"
|
|
<< " -tv.sharpness <value> Set TV effects custom sharpness to value 1.0 - 1.0\n"
|
|
<< " -tv.resolution <value> Set TV effects custom resolution to value 1.0 - 1.0\n"
|
|
<< " -tv.artifacts <value> Set TV effects custom artifacts to value 1.0 - 1.0\n"
|
|
<< " -tv.fringing <value> Set TV effects custom fringing to value 1.0 - 1.0\n"
|
|
<< " -tv.bleed <value> Set TV effects custom bleed to value 1.0 - 1.0\n"
|
|
<< endl
|
|
<< " -cheat <code> Use the specified cheatcode (see manual for description)\n"
|
|
<< " -loglevel <0|1|2> Set level of logging during application run\n"
|
|
<< " -logtoconsole <1|0> Log output to console/commandline\n"
|
|
<< " -joydeadzone <number> Sets 'deadzone' area for analog joysticks (0-29)\n"
|
|
<< " -joyallow4 <1|0> Allow all 4 directions on a joystick to be pressed simultaneously\n"
|
|
<< " -usemouse <always|\n"
|
|
<< " analog|\n"
|
|
<< " never> Use mouse as a controller as specified by ROM properties in given mode(see manual)\n"
|
|
<< " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n"
|
|
<< " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n"
|
|
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-20)\n"
|
|
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-20)\n"
|
|
<< " -saport <lr|rl> How to assign virtual ports to multiple Stelladaptor/2600-daptors\n"
|
|
<< " -ctrlcombo <1|0> Use key combos involving the Control key (Control-Q for quit may be disabled!)\n"
|
|
<< " -autoslot <1|0> Automatically switch to next save slot when state saving\n"
|
|
<< " -stats <1|0> Overlay console info during emulation\n"
|
|
<< " -fastscbios <1|0> Disable Supercharger BIOS progress loading bars\n"
|
|
<< " -snapsavedir <path> The directory to save snapshot files to\n"
|
|
<< " -snaploaddir <path> The directory to load snapshot files from\n"
|
|
<< " -snapname <int|rom> Name snapshots according to internal database or ROM\n"
|
|
<< " -sssingle <1|0> Generate single snapshot instead of many\n"
|
|
<< " -ss1x <1|0> Generate TIA snapshot in 1x mode (ignore scaling/effects)\n"
|
|
<< " -ssinterval <number Number of seconds between snapshots in continuous snapshot mode\n"
|
|
<< endl
|
|
<< " -rominfo <rom> Display detailed information for the given ROM\n"
|
|
<< " -listrominfo Display contents of stella.pro, one line per ROM entry\n"
|
|
<< " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n"
|
|
<< " -launcherres <WxH> The resolution to use in ROM launcher mode\n"
|
|
<< " -launcherfont <small|medium| Use the specified font in the ROM launcher\n"
|
|
<< " large>\n"
|
|
<< " -launcherexts <allfiles| Show files with the given extensions in ROM launcher\n"
|
|
<< " allroms| (exts is a ':' separated list of extensions)\n"
|
|
<< " exts\n"
|
|
<< " -romviewer <0|1|2> Show ROM info viewer at given zoom level in ROM launcher (0 for off)\n"
|
|
<< " -listdelay <delay> Time to wait between keypresses in list widgets (300-1000)\n"
|
|
<< " -mwheel <lines> Number of lines the mouse wheel will scroll in UI\n"
|
|
<< " -romdir <dir> Directory in which to load ROM files\n"
|
|
<< " -statedir <dir> Directory in which to save/load state files\n"
|
|
<< " -cheatfile <file> Full pathname of cheatfile database\n"
|
|
<< " -palettefile <file> Full pathname of user-defined palette file\n"
|
|
<< " -propsfile <file> Full pathname of ROM properties file\n"
|
|
<< " -nvramdir <dir> Directory in which to save/load flash/EEPROM files\n"
|
|
<< " -cfgdir <dir> Directory in which to save Distella config files\n"
|
|
<< " -avoxport <name> The name of the serial port where an AtariVox is connected\n"
|
|
<< " -holdreset Start the emulator with the Game Reset switch held down\n"
|
|
<< " -holdselect Start the emulator with the Game Select switch held down\n"
|
|
<< " -holdjoy0 <U,D,L,R,F> Start the emulator with the left joystick direction/fire button held down\n"
|
|
<< " -holdjoy1 <U,D,L,R,F> Start the emulator with the right joystick direction/fire button held down\n"
|
|
<< " -tiadriven <1|0> Drive unused TIA pins randomly on a read/peek\n"
|
|
<< " -cpurandom <1|0> Randomize the contents of CPU registers on reset\n"
|
|
<< " -ramrandom <1|0> Randomize the contents of RAM on reset\n"
|
|
<< " -maxres <WxH> Used by developers to force the maximum size of the application window\n"
|
|
<< " -help Show the text you're now reading\n"
|
|
#ifdef DEBUGGER_SUPPORT
|
|
<< endl
|
|
<< " The following options are meant for developers\n"
|
|
<< " Arguments are more fully explained in the manual\n"
|
|
<< endl
|
|
<< " -dis.resolve <1|0> Attempt to resolve code sections in disassembler\n"
|
|
<< " -dis.gfxformat <2|16> Set base to use for displaying GFX sections in disassembler\n"
|
|
<< " -dis.showaddr <1|0> Show opcode addresses in disassembler\n"
|
|
<< " -dis.relocate <1|0> Relocate calls out of address range in disassembler\n"
|
|
<< endl
|
|
<< " -dbg.res <WxH> The resolution to use in debugger mode\n"
|
|
<< " -dbg.fontstyle <0-3> Font style to use in debugger window (bold vs. normal)\n"
|
|
<< " -break <address> Set a breakpoint at 'address'\n"
|
|
<< " -debug Start in debugger mode\n"
|
|
<< endl
|
|
<< " -bs <arg> Sets the 'Cartridge.Type' (bankswitch) property\n"
|
|
<< " -type <arg> Same as using -bs\n"
|
|
<< " -channels <arg> Sets the 'Cartridge.Sound' property\n"
|
|
<< " -ld <arg> Sets the 'Console.LeftDifficulty' property\n"
|
|
<< " -rd <arg> Sets the 'Console.RightDifficulty' property\n"
|
|
<< " -tv <arg> Sets the 'Console.TelevisionType' property\n"
|
|
<< " -sp <arg> Sets the 'Console.SwapPorts' property\n"
|
|
<< " -lc <arg> Sets the 'Controller.Left' property\n"
|
|
<< " -rc <arg> Sets the 'Controller.Right' property\n"
|
|
<< " -bc <arg> Same as using both -lc and -rc\n"
|
|
<< " -cp <arg> Sets the 'Controller.SwapPaddles' property\n"
|
|
<< " -format <arg> Sets the 'Display.Format' property\n"
|
|
<< " -ystart <arg> Sets the 'Display.YStart' property\n"
|
|
<< " -height <arg> Sets the 'Display.Height' property\n"
|
|
<< " -pp <arg> Sets the 'Display.Phosphor' property\n"
|
|
<< " -ppblend <arg> Sets the 'Display.PPBlend' property\n"
|
|
#endif
|
|
<< endl << std::flush;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
const Variant& Settings::value(const string& key) const
|
|
{
|
|
// Try to find the named setting and answer its value
|
|
int idx = -1;
|
|
if((idx = getInternalPos(key)) != -1)
|
|
return myInternalSettings[idx].value;
|
|
else if((idx = getExternalPos(key)) != -1)
|
|
return myExternalSettings[idx].value;
|
|
else
|
|
return EmptyVariant;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Settings::setValue(const string& key, const Variant& value)
|
|
{
|
|
if(int idx = getInternalPos(key) != -1)
|
|
setInternal(key, value, idx);
|
|
else
|
|
setExternal(key, value);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Settings::saveConfig()
|
|
{
|
|
// Do a quick scan of the internal settings to see if any have
|
|
// changed. If not, we don't need to save them at all.
|
|
bool settingsChanged = false;
|
|
for(const auto& s: myInternalSettings)
|
|
{
|
|
if(s.value != s.initialValue)
|
|
{
|
|
settingsChanged = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!settingsChanged)
|
|
return;
|
|
|
|
ofstream out(myOSystem.configFile());
|
|
if(!out || !out.is_open())
|
|
{
|
|
myOSystem.logMessage("ERROR: Couldn't save settings file", 0);
|
|
return;
|
|
}
|
|
|
|
out << "; Stella configuration file" << endl
|
|
<< ";" << endl
|
|
<< "; Lines starting with ';' are comments and are ignored." << endl
|
|
<< "; Spaces and tabs are ignored." << endl
|
|
<< ";" << endl
|
|
<< "; Format MUST be as follows:" << endl
|
|
<< "; command = value" << endl
|
|
<< ";" << endl
|
|
<< "; Commmands are the same as those specified on the commandline," << endl
|
|
<< "; without the '-' character." << endl
|
|
<< ";" << endl
|
|
<< "; Values are the same as those allowed on the commandline." << endl
|
|
<< "; Boolean values are specified as 1 (or true) and 0 (or false)" << endl
|
|
<< ";" << endl;
|
|
|
|
// Write out each of the key and value pairs
|
|
for(const auto& s: myInternalSettings)
|
|
out << s.key << " = " << s.value << endl;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
int Settings::getInternalPos(const string& key) const
|
|
{
|
|
for(uInt32 i = 0; i < myInternalSettings.size(); ++i)
|
|
if(myInternalSettings[i].key == key)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
int Settings::getExternalPos(const string& key) const
|
|
{
|
|
for(uInt32 i = 0; i < myExternalSettings.size(); ++i)
|
|
if(myExternalSettings[i].key == key)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
int Settings::setInternal(const string& key, const Variant& value,
|
|
int pos, bool useAsInitial)
|
|
{
|
|
int idx = -1;
|
|
|
|
if(pos >= 0 && pos < int(myInternalSettings.size()) &&
|
|
myInternalSettings[pos].key == key)
|
|
{
|
|
idx = pos;
|
|
}
|
|
else
|
|
{
|
|
for(uInt32 i = 0; i < myInternalSettings.size(); ++i)
|
|
{
|
|
if(myInternalSettings[i].key == key)
|
|
{
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(idx != -1)
|
|
{
|
|
myInternalSettings[idx].key = key;
|
|
myInternalSettings[idx].value = value;
|
|
if(useAsInitial) myInternalSettings[idx].initialValue = value;
|
|
|
|
/*cerr << "modify internal: key = " << key
|
|
<< ", value = " << value
|
|
<< ", ivalue = " << myInternalSettings[idx].initialValue
|
|
<< " @ index = " << idx
|
|
<< endl;*/
|
|
}
|
|
else
|
|
{
|
|
Setting setting;
|
|
setting.key = key;
|
|
setting.value = value;
|
|
if(useAsInitial) setting.initialValue = value;
|
|
|
|
myInternalSettings.push_back(setting);
|
|
idx = int(myInternalSettings.size()) - 1;
|
|
|
|
/*cerr << "insert internal: key = " << key
|
|
<< ", value = " << value
|
|
<< ", ivalue = " << setting.initialValue
|
|
<< " @ index = " << idx
|
|
<< endl;*/
|
|
}
|
|
|
|
return idx;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
int Settings::setExternal(const string& key, const Variant& value,
|
|
int pos, bool useAsInitial)
|
|
{
|
|
int idx = -1;
|
|
|
|
if(pos >= 0 && pos < int(myExternalSettings.size()) &&
|
|
myExternalSettings[pos].key == key)
|
|
{
|
|
idx = pos;
|
|
}
|
|
else
|
|
{
|
|
for(uInt32 i = 0; i < myExternalSettings.size(); ++i)
|
|
{
|
|
if(myExternalSettings[i].key == key)
|
|
{
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(idx != -1)
|
|
{
|
|
myExternalSettings[idx].key = key;
|
|
myExternalSettings[idx].value = value;
|
|
if(useAsInitial) myExternalSettings[idx].initialValue = value;
|
|
|
|
/*cerr << "modify external: key = " << key
|
|
<< ", value = " << value
|
|
<< " @ index = " << idx
|
|
<< endl;*/
|
|
}
|
|
else
|
|
{
|
|
Setting setting;
|
|
setting.key = key;
|
|
setting.value = value;
|
|
if(useAsInitial) setting.initialValue = value;
|
|
|
|
myExternalSettings.push_back(setting);
|
|
idx = int(myExternalSettings.size()) - 1;
|
|
|
|
/*cerr << "insert external: key = " << key
|
|
<< ", value = " << value
|
|
<< " @ index = " << idx
|
|
<< endl;*/
|
|
}
|
|
|
|
return idx;
|
|
}
|