More restructuring of the OSystem and derived class interaction

- Each derived class no longer calls methods from the base class
- The base class now directly queries the derived class with a pure virtual method, making sure it is called
- Implemented 'basedir' commandline argument for Linux

Windows and macOS currently won't compile.  I'll work on those next.
This commit is contained in:
Stephen Anthony 2019-02-24 19:14:55 -03:30
parent 28d1113523
commit 88afab2d22
7 changed files with 139 additions and 99 deletions

View File

@ -96,7 +96,7 @@ void parseCommandLine(int ac, char* av[],
// configuration files are stored; we check for those next
if(key == "baseinappdir")
{
globalOpts[key] = true;
localOpts[key] = true;
continue;
}
@ -130,7 +130,7 @@ void checkForCustomBaseDir(Settings::Options& options)
// If both of these are activated, the 'base in app dir' takes precedence
auto it = options.find("baseinappdir");
if(it != options.end())
OSystem::overrideBaseDir();
OSystem::overrideBaseDirWithApp();
else
{
it = options.find("basedir");

View File

@ -169,6 +169,29 @@ bool OSystem::create()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::loadConfig(const Settings::Options& options)
{
// Get base directory and config file from derived class
// It will decide whether it can override its default location
getBaseDirAndConfig(myBaseDir, myConfigFile,
myDefaultSaveDir, myDefaultLoadDir,
ourOverrideBaseDirWithApp, ourOverrideBaseDir);
// Get fully-qualified pathnames, and make directories when needed
FilesystemNode node(myBaseDir);
if(!node.isDirectory())
node.makeDir();
myBaseDir = node.getPath();
myConfigFile = FilesystemNode(myConfigFile).getPath();
FilesystemNode save(myDefaultSaveDir);
if(!save.isDirectory())
save.makeDir();
myDefaultSaveDir = node.getPath();
FilesystemNode load(myDefaultLoadDir);
if(!load.isDirectory())
load.makeDir();
myDefaultLoadDir = node.getPath();
logMessage("Loading config options ...", 2);
mySettings->load(configFile(), options);
}
@ -241,22 +264,6 @@ void OSystem::setConfigPaths()
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setBaseDir(const string& basedir)
{
FilesystemNode node(basedir);
if(!node.isDirectory())
node.makeDir();
myBaseDir = node.getPath();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setConfigFile(const string& file)
{
myConfigFile = FilesystemNode(file).getPath();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBInitStatus OSystem::createFrameBuffer()
{
@ -734,3 +741,4 @@ void OSystem::mainLoop()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string OSystem::ourOverrideBaseDir = "";
bool OSystem::ourOverrideBaseDirWithApp = false;

View File

@ -282,6 +282,13 @@ class OSystem
*/
const FilesystemNode& romFile() const { return myRomFile; }
/**
The default locations for saving and loading various files that
don't already have a specific location.
*/
const string& defaultSaveDir() const { return myDefaultSaveDir; }
const string& defaultLoadDir() const { return myDefaultLoadDir; }
/**
Open the given ROM and return an array containing its contents.
Also, the properties database is updated with a valid ROM name
@ -391,13 +398,12 @@ class OSystem
derived classes are free to ignore this, as some can't use an
alternate base directory.
If the default path is used, this indicates to attempt to use the
application directory directly. Again, this is not supported on
all systems, so it may be simply ignored.
Alternatively, attempt to use the application directory directly.
Again, this is not supported on all systems, so it may be simply
ignored.
*/
static void overrideBaseDir(const string& path = "USE_APP_DIR") {
ourOverrideBaseDir = path;
}
static void overrideBaseDir(const string& path) { ourOverrideBaseDir = path; }
static void overrideBaseDirWithApp() { ourOverrideBaseDirWithApp = true; }
public:
//////////////////////////////////////////////////////////////////////
@ -431,27 +437,30 @@ class OSystem
*/
virtual void stateChanged(EventHandlerState state) { }
/**
Returns the default save and load paths for various files
(snapshots, disassembly, roms, etc). Since this varies greatly
among different systems and is the one directory that most end-users
care about (vs. config file stuff that usually isn't user-modifiable),
we create a special method for it.
*/
virtual string defaultSaveDir() const { return string("~") + BSPF::PATH_SEPARATOR; }
virtual string defaultLoadDir() const { return string("~") + BSPF::PATH_SEPARATOR; }
protected:
//////////////////////////////////////////////////////////////////////
// The following methods are system-specific and *must* be
// implemented in derived classes.
//////////////////////////////////////////////////////////////////////
/**
Set the base directory for all Stella files (these files may be
located in other places through settings).
*/
void setBaseDir(const string& basedir);
Determine the base directory and main configuration file from the
derived class. It can also use hints, as described below.
/**
Set the locations of config file
@param basedir The base directory for all configuration files
@param cfgfile The fully qualified pathname of the config file
(including the base directory)
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@param usedir A hint that the base dir should be set to this
parameter; not all ports can do this, so
they are free to ignore it
*/
void setConfigFile(const string& file);
virtual void getBaseDirAndConfig(string& basedir, string& cfgfile,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) = 0;
protected:
// Pointer to the EventHandler object
@ -519,11 +528,6 @@ class OSystem
// Indicates whether to stop the main loop
bool myQuitLoop;
// If not empty, a hint for derived classes to use this as the
// base directory (where all settings are stored)
// Derived classes are free to ignore it and use their own defaults
static string ourOverrideBaseDir;
private:
string myBaseDir;
string myStateDir;
@ -531,6 +535,8 @@ class OSystem
string mySnapshotLoadDir;
string myNVRamDir;
string myCfgDir;
string myDefaultSaveDir;
string myDefaultLoadDir;
string myCheatFile;
string myConfigFile;
@ -545,6 +551,12 @@ class OSystem
FpsMeter myFpsMeter;
// If not empty, a hint for derived classes to use this as the
// base directory (where all settings are stored)
// Derived classes are free to ignore it and use their own defaults
static string ourOverrideBaseDir;
static bool ourOverrideBaseDirWithApp;
private:
/**
Creates the various framebuffers/renderers available in this system.

View File

@ -21,36 +21,35 @@
#include "Version.hxx"
#include "OSystemUNIX.hxx"
/**
Each derived class is responsible for calling the following methods
in its constructor:
setBaseDir()
setConfigFile()
See OSystem.hxx for a further explanation
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OSystemUNIX::OSystemUNIX()
: OSystem()
void OSystemUNIX::getBaseDirAndConfig(string& basedir, string& cfgfile,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
{
// Use XDG_CONFIG_HOME if defined, otherwise use the default
const char* configDir = getenv("XDG_CONFIG_HOME");
if(configDir == nullptr) configDir = "~/.config";
basedir = string(configDir) + "/stella";
savedir = loaddir = "~/";
string stellaDir = string(configDir) + "/stella";
setBaseDir(stellaDir);
// Check to see if basedir overrides are active
if(useappdir)
cout << "ERROR: base dir in app folder not supported" << endl;
else if(usedir != "")
{
basedir = FilesystemNode(usedir).getPath();
savedir = loaddir = basedir;
}
// (Currently) non-documented alternative for using version-specific
// config file
ostringstream buf;
buf << stellaDir << "/stellarc" << "-" << STELLA_VERSION;
buf << basedir << "/stellarc" << "-" << STELLA_VERSION;
// Use version-specific config file only if it already exists
FilesystemNode altConfigFile(buf.str());
if(altConfigFile.exists() && altConfigFile.isWritable())
setConfigFile(altConfigFile.getPath());
cfgfile = altConfigFile.getPath();
else
setConfigFile(stellaDir + "/stellarc");
cfgfile = basedir + "/stellarc";
}

View File

@ -21,19 +21,39 @@
#include "OSystem.hxx"
/**
This class defines UNIX-like OS's (Linux) system specific settings.
This class defines an OSystem object for UNIX-like OS's (Linux).
It is responsible for completely implementing getBaseDirAndConfig(),
to set the base directory, config file location, and various other
save/load locations.
@author Stephen Anthony
*/
class OSystemUNIX : public OSystem
{
public:
/**
Create a new UNIX-specific operating system object
*/
OSystemUNIX();
OSystemUNIX() = default;
virtual ~OSystemUNIX() = default;
/**
Determine the base directory and main configuration file from the
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param cfgfile The fully qualified pathname of the config file
(including the base directory)
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@param usedir A hint that the base dir should be set to this
parameter; not all ports can do this, so
they are free to ignore it
*/
void getBaseDirAndConfig(string& basedir, string& cfgfile,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported
OSystemUNIX(const OSystemUNIX&) = delete;

View File

@ -21,22 +21,12 @@
#include "OSystemWINDOWS.hxx"
/**
Each derived class is responsible for calling the following methods
in its constructor:
setBaseDir()
setConfigFile()
See OSystem.hxx for a further explanation
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OSystemWINDOWS::OSystemWINDOWS()
: OSystem()
void OSystemWINDOWS::getBaseDirAndConfig(string& basedir, string& cfgfile,
string& savedir, string& loaddir,
bool useappdir, const string& usedir)
{
string basedir = "";
#if 0
// Check if the base directory should be overridden
// Shouldn't normally be necessary, but is useful for those people that
// don't want to clutter their 'My Documents' folder
@ -58,6 +48,7 @@ OSystemWINDOWS::OSystemWINDOWS()
if(basedir != "") overrideBasedir = true;
}
}
#endif
// If basedir hasn't been specified, use the 'home' directory
if(!overrideBasedir)
@ -75,15 +66,9 @@ OSystemWINDOWS::OSystemWINDOWS()
basedir = ".\\"; // otherwise, default to current directory
}
setBaseDir(basedir);
setConfigFile(basedir + "stella.ini");
// Create default save/load dir
FilesystemNode node(defaultSaveDir());
if(!node.exists())
node.makeDir();
cfgfile = basedir + "stella.ini";
}
#if 0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string OSystemWINDOWS::defaultSaveDir() const
{
@ -97,3 +82,4 @@ string OSystemWINDOWS::defaultLoadDir() const
{
return defaultSaveDir();
}
#endif

View File

@ -21,23 +21,38 @@
#include "OSystem.hxx"
/**
This class defines Windows system specific settings.
This class defines an OSystem object for Windows OS's.
It is responsible for completely implementing getBaseDirAndConfig(),
to set the base directory, config file location, and various other
save/load locations.
@author Stephen Anthony
*/
class OSystemWINDOWS : public OSystem
{
public:
/**
Create a new WINDOWS operating system object
*/
OSystemWINDOWS();
OSystemWINDOWS() = default;
virtual ~OSystemWINDOWS() = default;
public:
/**
Returns the default paths for loading/saving files.
Determine the base directory and main configuration file from the
derived class. It can also use hints, as described below.
@param basedir The base directory for all configuration files
@param cfgfile The fully qualified pathname of the config file
(including the base directory)
@param savedir The default directory to save various other files
@param loaddir The default directory to load various other files
@param useappdir A hint that the base dir should be set to the
app directory; not all ports can do this, so
they are free to ignore it
@param usedir A hint that the base dir should be set to this
parameter; not all ports can do this, so
they are free to ignore it
*/
string defaultSaveDir() const override;
string defaultLoadDir() const override;
void getBaseDirAndConfig(string& basedir, string& cfgfile,
string& savedir, string& loaddir,
bool useappdir, const string& usedir) override;
private:
// Following constructors and assignment operators not supported