Reworked Windows config file locations to be in the users home directory, under Application Data (or equivalent). Also, the '~' character now more properly refers to the actual home directory of the user, and not their 'My Documents' folder (ie, it refers to their PROFILE name). Config files are now by default stored in APPDATA, which for XP and Vista is ~/Application Data/. The ability to override this with basedir.txt is still available, but not recommended. This is the *LAST* time the Windows config file locations will be changed, so everyone will have to get used to it.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1778 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-06-18 17:08:09 +00:00
parent bf85802526
commit 4d9eeae717
9 changed files with 149 additions and 91 deletions

View File

@ -337,7 +337,7 @@ string Debugger::getSourceLines(int addr) const
void Debugger::autoExec() void Debugger::autoExec()
{ {
// autoexec.stella is always run // autoexec.stella is always run
const string& autoexec = myOSystem->baseDir(false) + BSPF_PATH_SEPARATOR + const string& autoexec = myOSystem->baseDir() + BSPF_PATH_SEPARATOR +
"autoexec.stella"; "autoexec.stella";
myPrompt->print("autoExec():\n" + myParser->exec(autoexec) + "\n"); myPrompt->print("autoExec():\n" + myParser->exec(autoexec) + "\n");

View File

@ -272,52 +272,52 @@ bool OSystem::create()
void OSystem::setConfigPaths() void OSystem::setConfigPaths()
{ {
// Paths are saved with special characters preserved ('~' or '.') // Paths are saved with special characters preserved ('~' or '.')
// Internally, we expand them so the rest of the codebase doesn't // We do some error checking here, so the rest of the codebase doesn't
// have to worry about it // have to worry about it
FilesystemNode node; FilesystemNode node;
string s; string s;
s = mySettings->getString("statedir"); s = mySettings->getString("statedir");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "state"; if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "state";
mySettings->setString("statedir", s);
node = FilesystemNode(s); node = FilesystemNode(s);
myStateDir = node.getPath(); myStateDir = node.getPath();
mySettings->setString("statedir", node.getRelativePath());
if(!node.isDirectory()) if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myStateDir); AbstractFilesystemNode::makeDir(myStateDir);
s = mySettings->getString("ssdir"); s = mySettings->getString("ssdir");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "snapshots"; if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "snapshots";
mySettings->setString("ssdir", s);
node = FilesystemNode(s); node = FilesystemNode(s);
mySnapshotDir = node.getPath(); mySnapshotDir = node.getPath();
mySettings->setString("ssdir", node.getRelativePath());
if(!node.isDirectory()) if(!node.isDirectory())
AbstractFilesystemNode::makeDir(mySnapshotDir); AbstractFilesystemNode::makeDir(mySnapshotDir);
s = mySettings->getString("eepromdir"); s = mySettings->getString("eepromdir");
if(s == "") s = myBaseDir; if(s == "") s = myBaseDir;
mySettings->setString("eepromdir", s);
node = FilesystemNode(s); node = FilesystemNode(s);
myEEPROMDir = node.getPath(); myEEPROMDir = node.getPath();
mySettings->setString("eepromdir", node.getRelativePath());
if(!node.isDirectory()) if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myEEPROMDir); AbstractFilesystemNode::makeDir(myEEPROMDir);
s = mySettings->getString("cheatfile"); s = mySettings->getString("cheatfile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.cht"; if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.cht";
mySettings->setString("cheatfile", s);
node = FilesystemNode(s); node = FilesystemNode(s);
myCheatFile = node.getPath(); myCheatFile = node.getPath();
mySettings->setString("cheatfile", node.getRelativePath());
s = mySettings->getString("palettefile"); s = mySettings->getString("palettefile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pal"; if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pal";
mySettings->setString("palettefile", s);
node = FilesystemNode(s); node = FilesystemNode(s);
myPaletteFile = node.getPath(); myPaletteFile = node.getPath();
mySettings->setString("palettefile", node.getRelativePath());
s = mySettings->getString("propsfile"); s = mySettings->getString("propsfile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pro"; if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pro";
mySettings->setString("propsfile", s);
node = FilesystemNode(s); node = FilesystemNode(s);
myPropertiesFile = node.getPath(); myPropertiesFile = node.getPath();
mySettings->setString("propsfile", node.getRelativePath());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -332,11 +332,10 @@ void OSystem::setUIPalette()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setBaseDir(const string& basedir) void OSystem::setBaseDir(const string& basedir)
{ {
myBaseDir = basedir; FilesystemNode node(basedir);
FilesystemNode node(myBaseDir); myBaseDir = node.getPath();
myBaseDirExpanded = node.getPath();
if(!node.isDirectory()) if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myBaseDirExpanded); AbstractFilesystemNode::makeDir(myBaseDir);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -767,14 +766,13 @@ uInt8* OSystem::openROM(string file, string& md5, uInt32& size)
if(!myPropSet->getMD5(md5, props)) if(!myPropSet->getMD5(md5, props))
{ {
// Get the filename from the rom pathname // Get the filename from the rom pathname
string::size_type pos = file.find_last_of(BSPF_PATH_SEPARATOR); string::size_type pos = file.find_last_of("/\\");
if(pos+1 != string::npos) if(pos != string::npos) file = file.substr(pos+1);
{
props.set(Cartridge_MD5, md5); props.set(Cartridge_MD5, md5);
props.set(Cartridge_Name, file.substr(pos+1)); props.set(Cartridge_Name, file);
myPropSet->insert(props, false); myPropSet->insert(props, false);
} }
}
return image; return image;
} }

View File

@ -251,8 +251,7 @@ class OSystem
/** /**
Return the default full/complete directory name for storing data. Return the default full/complete directory name for storing data.
*/ */
const string& baseDir(bool expanded = true) const const string& baseDir() const { return myBaseDir; }
{ return expanded ? myBaseDirExpanded : myBaseDir; }
/** /**
Return the full/complete directory name for storing state files. Return the full/complete directory name for storing state files.

View File

@ -216,7 +216,7 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
break; break;
case kBaseDirCmd: case kBaseDirCmd:
_node = FilesystemNode(instance().baseDir(false)); _node = FilesystemNode(instance().baseDir());
updateListing(); updateListing();
break; break;

View File

@ -197,23 +197,40 @@ void FileSnapDialog::saveConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FileSnapDialog::setDefaults() void FileSnapDialog::setDefaults()
{ {
const string& basedir = instance().baseDir(false); // get relative basedir FilesystemNode node;
const string& romdir = "~"; string basedir = instance().baseDir();
const string& statedir = basedir + BSPF_PATH_SEPARATOR + "state";
const string& cheatfile = basedir + BSPF_PATH_SEPARATOR + "stella.cht"; const char* end = basedir.c_str() + basedir.length();
const string& palettefile = basedir + BSPF_PATH_SEPARATOR + "stella.pal"; if(basedir.compare(basedir.length()-1, 1, BSPF_PATH_SEPARATOR, 0, 1) != 0)
const string& propsfile = basedir + BSPF_PATH_SEPARATOR + "stella.pro"; basedir.append(BSPF_PATH_SEPARATOR);
const string& ssdir = basedir + BSPF_PATH_SEPARATOR + "snapshots";
node = FilesystemNode("~");
myRomPath->setEditString(node.getRelativePath());
const string& statedir = basedir + "state";
node = FilesystemNode(statedir);
myStatePath->setEditString(node.getRelativePath());
const string& cheatfile = basedir + "stella.cht";
node = FilesystemNode(cheatfile);
myCheatFile->setEditString(node.getRelativePath());
const string& palettefile = basedir + "stella.pal";
node = FilesystemNode(palettefile);
myPaletteFile->setEditString(node.getRelativePath());
const string& propsfile = basedir + "stella.pro";
node = FilesystemNode(propsfile);
myPropsFile->setEditString(node.getRelativePath());
const string& eepromdir = basedir; const string& eepromdir = basedir;
node = FilesystemNode(eepromdir);
myEEPROMPath->setEditString(node.getRelativePath());
myRomPath->setEditString(romdir); const string& ssdir = basedir + "snapshots";
myStatePath->setEditString(statedir); node = FilesystemNode(ssdir);
myCheatFile->setEditString(cheatfile); mySnapPath->setEditString(node.getRelativePath());
myPaletteFile->setEditString(palettefile);
myPropsFile->setEditString(propsfile);
myEEPROMPath->setEditString(eepromdir);
mySnapPath->setEditString(ssdir);
mySnapSingle->setState(true); mySnapSingle->setState(true);
mySnap1x->setState(false); mySnap1x->setState(false);
} }

View File

@ -58,54 +58,9 @@
#endif #endif
#include "FSNode.hxx" #include "FSNode.hxx"
#include "HomeFinder.hxx"
/* static HomeFinder myHomeFinder;
* Used to determine the location of the 'My Documents' folder.
*
* Win98 and earlier don't have SHGetFolderPath in shell32.dll.
* Microsoft recommend that we load shfolder.dll at run time and
* access the function through that.
*
* shfolder.dll is loaded dynamically in the constructor, and unloaded in
* the destructor
*
* The class makes SHGetFolderPath available through its function operator.
* It will work on all versions of Windows >= Win95.
*
* This code was borrowed from the Lyx project.
*/
class MyDocumentsFinder
{
public:
MyDocumentsFinder() : myFolderModule(0), myFolderPathFunc(0)
{
myFolderModule = LoadLibrary("shfolder.dll");
if(myFolderModule)
myFolderPathFunc = reinterpret_cast<function_pointer>
(::GetProcAddress(myFolderModule, "SHGetFolderPathA"));
}
~MyDocumentsFinder() { if(myFolderModule) FreeLibrary(myFolderModule); }
/** Wrapper for SHGetFolderPathA, returning the 'My Documents' folder
(or an empty string if the folder couldn't be determined. */
string getPath() const
{
if(!myFolderPathFunc) return "";
char folder_path[MAX_PATH];
HRESULT const result = (myFolderPathFunc)
(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, folder_path);
return (result == 0) ? folder_path : "";
}
private:
typedef HRESULT (__stdcall * function_pointer)(HWND, int, HANDLE, DWORD, LPCSTR);
HMODULE myFolderModule;
function_pointer myFolderPathFunc;
};
static MyDocumentsFinder myDocsFinder;
/* /*
* Implementation of the Stella file system API based on Windows API. * Implementation of the Stella file system API based on Windows API.
@ -283,15 +238,15 @@ WindowsFilesystemNode::WindowsFilesystemNode()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WindowsFilesystemNode::WindowsFilesystemNode(const string& p) WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
{ {
// Expand "~\\" to the 'My Documents' directory // Expand "~\" to the 'My Documents' directory
if ( p.length() >= 2 && p[0] == '~' && p[1] == '\\') if ( p.length() >= 2 && p[0] == '~' && p[1] == '\\')
{ {
_path = myDocsFinder.getPath(); _path = myHomeFinder.getHomePath();
// Skip over the tilda. We know that p contains at least // Skip over the tilda. We know that p contains at least
// two chars, so this is safe: // two chars, so this is safe:
_path += p.c_str() + 1; _path += p.c_str() + 1;
} }
// Expand ".\\" to the current directory // Expand ".\" to the current directory
else if ( p.length() >= 2 && p[0] == '.' && p[1] == '\\') else if ( p.length() >= 2 && p[0] == '.' && p[1] == '\\')
{ {
char path[MAX_PATH]; char path[MAX_PATH];
@ -333,12 +288,12 @@ WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
string WindowsFilesystemNode::getRelativePath() const string WindowsFilesystemNode::getRelativePath() const
{ {
// If the path starts with the home directory, replace it with '~' // If the path starts with the home directory, replace it with '~'
const string& home = myDocsFinder.getPath(); const string& home = myHomeFinder.getHomePath();
if(home != "") if(home != "")
{ {
// Windows file system not case sensitive // Windows file system not case sensitive
int len = home.length(); int len = home.length();
if(BSPF_strncasecmp(home.c_str(), _path.substr(0, len).c_str()) == 0) if(BSPF_strncasecmp(home.c_str(), _path.substr(0, len).c_str(), len) == 0)
{ {
string path = "~"; string path = "~";
const char* offset = _path.c_str() + len; const char* offset = _path.c_str() + len;

78
src/win32/HomeFinder.hxx Normal file
View File

@ -0,0 +1,78 @@
//============================================================================
//
// 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-2009 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include <shlobj.h>
/*
* Used to determine the location of the 'HOME' and 'APPDATA' folders.
*
* Win98 and earlier don't have SHGetFolderPath in shell32.dll.
* Microsoft recommend that we load shfolder.dll at run time and
* access the function through that.
*
* shfolder.dll is loaded dynamically in the constructor, and unloaded in
* the destructor
*
* The class makes SHGetFolderPath available through its function operator.
* It will work on all versions of Windows >= Win95.
*
* This code was borrowed from the Lyx project.
*/
class HomeFinder
{
public:
HomeFinder() : myFolderModule(0), myFolderPathFunc(0)
{
myFolderModule = LoadLibrary("shfolder.dll");
if(myFolderModule)
myFolderPathFunc = reinterpret_cast<function_pointer>
(::GetProcAddress(myFolderModule, "SHGetFolderPathA"));
}
~HomeFinder() { if(myFolderModule) FreeLibrary(myFolderModule); }
/** Wrapper for SHGetFolderPathA, returning the 'HOME/User' folder
(or an empty string if the folder couldn't be determined. */
string getHomePath() const
{
if(!myFolderPathFunc) return "";
char folder_path[MAX_PATH];
HRESULT const result = (myFolderPathFunc)
(NULL, CSIDL_PROFILE | CSIDL_FLAG_CREATE, NULL, 0, folder_path);
return (result == 0) ? folder_path : "";
}
/** Wrapper for SHGetFolderPathA, returning the 'APPDATA' folder
(or an empty string if the folder couldn't be determined. */
string getAppDataPath() const
{
if(!myFolderPathFunc) return "";
char folder_path[MAX_PATH];
HRESULT const result = (myFolderPathFunc)
(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, folder_path);
return (result == 0) ? folder_path : "";
}
private:
typedef HRESULT (__stdcall * function_pointer)(HWND, int, HANDLE, DWORD, LPCSTR);
HMODULE myFolderModule;
function_pointer myFolderPathFunc;
};

View File

@ -18,6 +18,7 @@
#include "bspf.hxx" #include "bspf.hxx"
#include "FSNode.hxx" #include "FSNode.hxx"
#include "HomeFinder.hxx"
#include "OSystem.hxx" #include "OSystem.hxx"
#include "OSystemWin32.hxx" #include "OSystemWin32.hxx"
@ -63,9 +64,15 @@ OSystemWin32::OSystemWin32()
// If basedir hasn't been specified, use the 'home' directory // If basedir hasn't been specified, use the 'home' directory
if(!overrideBasedir) if(!overrideBasedir)
{ {
FilesystemNode home("~\\"); HomeFinder homefinder;
if(home.isDirectory()) FilesystemNode appdata(homefinder.getAppDataPath());
basedir = "~\\Stella"; if(appdata.isDirectory())
{
basedir = appdata.getRelativePath();
if(basedir.length() > 1 && basedir[basedir.length()-1] != '\\')
basedir += '\\';
basedir += "Stella";
}
else else
basedir = "."; // otherwise, default to current directory basedir = "."; // otherwise, default to current directory
} }

View File

@ -972,6 +972,10 @@
RelativePath="..\common\GLShaderProgs.hxx" RelativePath="..\common\GLShaderProgs.hxx"
> >
</File> </File>
<File
RelativePath=".\HomeFinder.hxx"
>
</File>
<File <File
RelativePath="..\win32\OSystemWin32.hxx" RelativePath="..\win32\OSystemWin32.hxx"
> >