* remove EmuDirectory from the core
* rework OpenLocalFile(), make the code more elegant, also fixes #352
This commit is contained in:
parent
f08b87b41f
commit
60a728283e
|
@ -23,8 +23,6 @@
|
|||
#include "Platform.h"
|
||||
|
||||
|
||||
extern char* EmuDirectory;
|
||||
|
||||
namespace Config
|
||||
{
|
||||
|
||||
|
@ -111,20 +109,7 @@ void Load()
|
|||
void Save()
|
||||
{
|
||||
FILE* f = Platform::OpenLocalFile(kConfigFile, "w");
|
||||
if (!f)
|
||||
{
|
||||
int dirlen = strlen(EmuDirectory);
|
||||
int filelen = strlen(kConfigFile);
|
||||
char* path = new char[dirlen + 1 + filelen + 1];
|
||||
strncpy(&path[0], EmuDirectory, dirlen);
|
||||
path[dirlen] = '/';
|
||||
strncpy(&path[dirlen+1], kConfigFile, filelen);
|
||||
path[dirlen+1+filelen] = '\0';
|
||||
|
||||
f = Platform::OpenFile(path, "w");
|
||||
delete[] path;
|
||||
if (!f) return;
|
||||
}
|
||||
if (!f) return;
|
||||
|
||||
ConfigEntry* entry = &ConfigFile[0];
|
||||
int c = 0;
|
||||
|
|
|
@ -36,7 +36,8 @@ void StopEmu();
|
|||
// * current working directory
|
||||
// * emulator directory (essentially where the melonDS executable is) if supported
|
||||
// * any platform-specific application data directories
|
||||
// requires that the file already exist.
|
||||
// in create mode, if the file doesn't exist, it will be created in the emulator
|
||||
// directory if supported, or in the current directory otherwise
|
||||
|
||||
FILE* OpenFile(const char* path, const char* mode, bool mustexist=false);
|
||||
FILE* OpenLocalFile(const char* path, const char* mode);
|
||||
|
|
|
@ -138,131 +138,118 @@ FILE* OpenLocalFile(const char* path, const char* mode)
|
|||
bool relpath = false;
|
||||
int pathlen = strlen(path);
|
||||
|
||||
#ifdef __WIN32__
|
||||
if (pathlen > 3)
|
||||
{
|
||||
if (path[1] == ':' && path[2] == '\\')
|
||||
return OpenFile(path, mode);
|
||||
}
|
||||
#else
|
||||
if (pathlen > 1)
|
||||
{
|
||||
if (path[0] == '/')
|
||||
return OpenFile(path, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pathlen >= 3)
|
||||
{
|
||||
if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path[2] == '\\'))
|
||||
relpath = true;
|
||||
}
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
if (pathlen > 3)
|
||||
int emudirlen = strlen(EmuDirectory);
|
||||
char* emudirpath;
|
||||
if (emudirlen)
|
||||
{
|
||||
if (path[1] == ':' && path[2] == '\\')
|
||||
return OpenFile(path, mode);
|
||||
int len = emudirlen + 1 + pathlen + 1;
|
||||
emudirpath = new char[len];
|
||||
strncpy(&emudirpath[0], EmuDirectory, emudirlen);
|
||||
emudirpath[emudirlen] = '\\';
|
||||
strncpy(&emudirpath[emudirlen+1], path, pathlen);
|
||||
emudirpath[emudirlen+1+pathlen] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
emudirpath = new char[pathlen+1];
|
||||
strncpy(&emudirpath[0], path, pathlen);
|
||||
emudirpath[pathlen] = '\0';
|
||||
}
|
||||
|
||||
// Locations are application directory, and AppData/melonDS on windows
|
||||
// Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonds on Linux
|
||||
|
||||
FILE* f;
|
||||
|
||||
// First check current working directory
|
||||
f = OpenFile(path, mode, true);
|
||||
if (f) return f;
|
||||
if (f) { delete[] emudirpath; return f; }
|
||||
|
||||
// then emu directory
|
||||
{
|
||||
int dirlen = strlen(EmuDirectory);
|
||||
if (dirlen)
|
||||
{
|
||||
int len = dirlen + 1 + pathlen + 1;
|
||||
char* tmp = new char[len];
|
||||
strncpy(&tmp[0], EmuDirectory, dirlen);
|
||||
tmp[dirlen] = '\\';
|
||||
strncpy(&tmp[dirlen+1], path, pathlen);
|
||||
tmp[dirlen+1+pathlen] = '\0';
|
||||
f = OpenFile(emudirpath, mode, true);
|
||||
if (f) { delete[] emudirpath; return f; }
|
||||
|
||||
f = OpenFile(tmp, mode, true);
|
||||
delete[] tmp;
|
||||
if (f) return f;
|
||||
}
|
||||
}
|
||||
#ifdef __WIN32__
|
||||
|
||||
// a path relative to AppData wouldn't make much sense
|
||||
if (relpath) return NULL;
|
||||
if (!relpath)
|
||||
{
|
||||
// Now check AppData
|
||||
PWSTR appDataPath = NULL;
|
||||
SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath);
|
||||
if (!appDataPath)
|
||||
return NULL;
|
||||
|
||||
// Now check AppData
|
||||
PWSTR appDataPath = NULL;
|
||||
SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath);
|
||||
if (!appDataPath)
|
||||
return NULL;
|
||||
// this will be more than enough
|
||||
WCHAR fatperm[4];
|
||||
fatperm[0] = mode[0];
|
||||
fatperm[1] = mode[1];
|
||||
fatperm[2] = mode[2];
|
||||
fatperm[3] = 0;
|
||||
|
||||
// this will be more than enough
|
||||
WCHAR fatperm[4];
|
||||
fatperm[0] = mode[0];
|
||||
fatperm[1] = mode[1];
|
||||
fatperm[2] = mode[2];
|
||||
fatperm[3] = 0;
|
||||
int fnlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
|
||||
if (fnlen < 1) return NULL;
|
||||
WCHAR* wfileName = new WCHAR[fnlen];
|
||||
int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, wfileName, fnlen);
|
||||
if (res != fnlen) { delete[] wfileName; return NULL; } // checkme?
|
||||
|
||||
int fnlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
|
||||
if (fnlen < 1) return NULL;
|
||||
WCHAR* wfileName = new WCHAR[fnlen];
|
||||
int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, wfileName, fnlen);
|
||||
if (res != fnlen) { delete[] wfileName; return NULL; } // checkme?
|
||||
const WCHAR* appdir = L"\\melonDS\\";
|
||||
|
||||
const WCHAR* appdir = L"\\melonDS\\";
|
||||
int pos = wcslen(appDataPath);
|
||||
void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR));
|
||||
if (!ptr) { delete[] wfileName; return NULL; } // oh well
|
||||
appDataPath = (PWSTR)ptr;
|
||||
|
||||
int pos = wcslen(appDataPath);
|
||||
void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR));
|
||||
if (!ptr) { delete[] wfileName; return NULL; } // oh well
|
||||
appDataPath = (PWSTR)ptr;
|
||||
wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir);
|
||||
wcscpy(&appDataPath[pos], wfileName);
|
||||
|
||||
wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir);
|
||||
wcscpy(&appDataPath[pos], wfileName);
|
||||
|
||||
f = _wfopen(appDataPath, L"rb");
|
||||
if (f) f = _wfreopen(appDataPath, fatperm, f);
|
||||
CoTaskMemFree(appDataPath);
|
||||
delete[] wfileName;
|
||||
if (f) return f;
|
||||
|
||||
return NULL;
|
||||
f = _wfopen(appDataPath, L"rb");
|
||||
if (f) f = _wfreopen(appDataPath, fatperm, f);
|
||||
CoTaskMemFree(appDataPath);
|
||||
delete[] wfileName;
|
||||
if (f) { delete[] emudirpath; return f; }
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (pathlen > 1)
|
||||
if (!relpath)
|
||||
{
|
||||
if (path[0] == '/')
|
||||
return OpenFile(path, mode);
|
||||
// Now check XDG_CONFIG_HOME
|
||||
// TODO: check for memory leak there
|
||||
std::string fullpath = std::string(g_get_user_config_dir()) + "/melonds/" + path;
|
||||
f = OpenFile(fullpath.c_str(), mode, true);
|
||||
if (f) { delete[] emudirpath; return f; }
|
||||
}
|
||||
|
||||
// Locations are application directory, and XDG_CONFIG_HOME/melonds
|
||||
|
||||
FILE* f;
|
||||
|
||||
// First check current working directory
|
||||
f = OpenFile(path, mode, true);
|
||||
if (f) return f;
|
||||
|
||||
// then emu directory
|
||||
{
|
||||
int dirlen = strlen(EmuDirectory);
|
||||
if (dirlen)
|
||||
{
|
||||
int len = dirlen + 1 + pathlen + 1;
|
||||
char* tmp = new char[len];
|
||||
strncpy(&tmp[0], EmuDirectory, dirlen);
|
||||
tmp[dirlen] = '/';
|
||||
strncpy(&tmp[dirlen+1], path, pathlen);
|
||||
tmp[dirlen+1+pathlen] = '\0';
|
||||
|
||||
f = OpenFile(tmp, mode, true);
|
||||
delete[] tmp;
|
||||
if (f) return f;
|
||||
}
|
||||
}
|
||||
|
||||
if (relpath) return NULL;
|
||||
|
||||
// Now check XDG_CONFIG_HOME
|
||||
// TODO: check for memory leak there
|
||||
std::string fullpath = std::string(g_get_user_config_dir()) + "/melonds/" + path;
|
||||
f = OpenFile(fullpath.c_str(), mode, true);
|
||||
if (f) return f;
|
||||
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
|
||||
if (mode[0] != 'r')
|
||||
{
|
||||
f = OpenFile(emudirpath, mode);
|
||||
if (f) { delete[] emudirpath; return f; }
|
||||
}
|
||||
|
||||
delete[] emudirpath;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue