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()
{
// autoexec.stella is always run
const string& autoexec = myOSystem->baseDir(false) + BSPF_PATH_SEPARATOR +
const string& autoexec = myOSystem->baseDir() + BSPF_PATH_SEPARATOR +
"autoexec.stella";
myPrompt->print("autoExec():\n" + myParser->exec(autoexec) + "\n");

View File

@ -272,52 +272,52 @@ bool OSystem::create()
void OSystem::setConfigPaths()
{
// 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
FilesystemNode node;
string s;
s = mySettings->getString("statedir");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "state";
mySettings->setString("statedir", s);
node = FilesystemNode(s);
myStateDir = node.getPath();
mySettings->setString("statedir", node.getRelativePath());
if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myStateDir);
s = mySettings->getString("ssdir");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "snapshots";
mySettings->setString("ssdir", s);
node = FilesystemNode(s);
mySnapshotDir = node.getPath();
mySettings->setString("ssdir", node.getRelativePath());
if(!node.isDirectory())
AbstractFilesystemNode::makeDir(mySnapshotDir);
s = mySettings->getString("eepromdir");
if(s == "") s = myBaseDir;
mySettings->setString("eepromdir", s);
node = FilesystemNode(s);
myEEPROMDir = node.getPath();
mySettings->setString("eepromdir", node.getRelativePath());
if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myEEPROMDir);
s = mySettings->getString("cheatfile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.cht";
mySettings->setString("cheatfile", s);
node = FilesystemNode(s);
myCheatFile = node.getPath();
mySettings->setString("cheatfile", node.getRelativePath());
s = mySettings->getString("palettefile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pal";
mySettings->setString("palettefile", s);
node = FilesystemNode(s);
myPaletteFile = node.getPath();
mySettings->setString("palettefile", node.getRelativePath());
s = mySettings->getString("propsfile");
if(s == "") s = myBaseDir + BSPF_PATH_SEPARATOR + "stella.pro";
mySettings->setString("propsfile", s);
node = FilesystemNode(s);
myPropertiesFile = node.getPath();
mySettings->setString("propsfile", node.getRelativePath());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -332,11 +332,10 @@ void OSystem::setUIPalette()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setBaseDir(const string& basedir)
{
myBaseDir = basedir;
FilesystemNode node(myBaseDir);
myBaseDirExpanded = node.getPath();
FilesystemNode node(basedir);
myBaseDir = node.getPath();
if(!node.isDirectory())
AbstractFilesystemNode::makeDir(myBaseDirExpanded);
AbstractFilesystemNode::makeDir(myBaseDir);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -767,13 +766,12 @@ uInt8* OSystem::openROM(string file, string& md5, uInt32& size)
if(!myPropSet->getMD5(md5, props))
{
// Get the filename from the rom pathname
string::size_type pos = file.find_last_of(BSPF_PATH_SEPARATOR);
if(pos+1 != string::npos)
{
props.set(Cartridge_MD5, md5);
props.set(Cartridge_Name, file.substr(pos+1));
myPropSet->insert(props, false);
}
string::size_type pos = file.find_last_of("/\\");
if(pos != string::npos) file = file.substr(pos+1);
props.set(Cartridge_MD5, md5);
props.set(Cartridge_Name, file);
myPropSet->insert(props, false);
}
return image;

View File

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

View File

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

View File

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

View File

@ -58,54 +58,9 @@
#endif
#include "FSNode.hxx"
#include "HomeFinder.hxx"
/*
* 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;
static HomeFinder myHomeFinder;
/*
* Implementation of the Stella file system API based on Windows API.
@ -283,15 +238,15 @@ WindowsFilesystemNode::WindowsFilesystemNode()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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] == '\\')
{
_path = myDocsFinder.getPath();
_path = myHomeFinder.getHomePath();
// Skip over the tilda. We know that p contains at least
// two chars, so this is safe:
_path += p.c_str() + 1;
}
// Expand ".\\" to the current directory
// Expand ".\" to the current directory
else if ( p.length() >= 2 && p[0] == '.' && p[1] == '\\')
{
char path[MAX_PATH];
@ -333,12 +288,12 @@ WindowsFilesystemNode::WindowsFilesystemNode(const string& p)
string WindowsFilesystemNode::getRelativePath() const
{
// If the path starts with the home directory, replace it with '~'
const string& home = myDocsFinder.getPath();
const string& home = myHomeFinder.getHomePath();
if(home != "")
{
// Windows file system not case sensitive
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 = "~";
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 "FSNode.hxx"
#include "HomeFinder.hxx"
#include "OSystem.hxx"
#include "OSystemWin32.hxx"
@ -63,9 +64,15 @@ OSystemWin32::OSystemWin32()
// If basedir hasn't been specified, use the 'home' directory
if(!overrideBasedir)
{
FilesystemNode home("~\\");
if(home.isDirectory())
basedir = "~\\Stella";
HomeFinder homefinder;
FilesystemNode appdata(homefinder.getAppDataPath());
if(appdata.isDirectory())
{
basedir = appdata.getRelativePath();
if(basedir.length() > 1 && basedir[basedir.length()-1] != '\\')
basedir += '\\';
basedir += "Stella";
}
else
basedir = "."; // otherwise, default to current directory
}

View File

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