mirror of https://github.com/stella-emu/stella.git
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:
parent
bf85802526
commit
4d9eeae717
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -972,6 +972,10 @@
|
|||
RelativePath="..\common\GLShaderProgs.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\HomeFinder.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\win32\OSystemWin32.hxx"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue