Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CommonPaths: Add Steam-specific user directory and clean up #11459

Merged
merged 7 commits into from
Feb 5, 2023
48 changes: 33 additions & 15 deletions Source/Core/Common/CommonPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,44 @@
#define DIR_SEP "/"
#define DIR_SEP_CHR '/'

// The user data dir
// The current working directory
#define ROOT_DIR "."

// The normal user directory
#ifndef STEAM
#ifdef _WIN32
#define USERDATA_DIR "User"
#define DOLPHIN_DATA_DIR "Dolphin"
#elif defined __APPLE__
// On OS X, USERDATA_DIR exists within the .app, but *always* reference
// the copy in Application Support instead! (Copied on first run)
// You can use the File::GetUserPath() util for this
#define USERDATA_DIR "Contents/Resources/User"
#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin"
#elif defined ANDROID
#define USERDATA_DIR "user"
#define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu"
#define NOMEDIA_FILE ".nomedia"
#define NORMAL_USER_DIR "Dolphin Emulator"
#elif defined(__APPLE__)
#define NORMAL_USER_DIR "Library/Application Support/Dolphin"
OatmealDome marked this conversation as resolved.
Show resolved Hide resolved
#elif defined(ANDROID)
#define NORMAL_USER_DIR "/sdcard/dolphin-emu"
#else
#define NORMAL_USER_DIR "dolphin-emu"
#endif
#else // ifndef STEAM
#ifdef _WIN32
#define NORMAL_USER_DIR "Dolphin Emulator (Steam)"
#elif defined(__APPLE__)
#define NORMAL_USER_DIR "Library/Application Support/Dolphin (Steam)"
delroth marked this conversation as resolved.
Show resolved Hide resolved
#else
#define NORMAL_USER_DIR "dolphin-emu-steam"
#endif
#endif

// The portable user directory
#ifdef _WIN32
#define PORTABLE_USER_DIR "User"
#elif defined(__APPLE__)
#define PORTABLE_USER_DIR "User"
#define EMBEDDED_USER_DIR "Contents/Resources/User"
#else
#define USERDATA_DIR "user"
#define DOLPHIN_DATA_DIR "dolphin-emu"
#define PORTABLE_USER_DIR "user"
OatmealDome marked this conversation as resolved.
Show resolved Hide resolved
#define EMBEDDED_USER_DIR PORTABLE_USER_DIR
#endif

// Flag file to prevent media scanning from indexing a directory
#define NOMEDIA_FILE ".nomedia"

// Dirs in both User and Sys
// Legacy setups used /JAP/ while newer setups use /JPN/ by default.
#define EUR_DIR "EUR"
Expand Down
62 changes: 43 additions & 19 deletions Source/Core/UICommon/UICommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,22 @@ void SetUserDirectory(std::string custom_path)
// -> Use AppData\Roaming\Dolphin Emulator as the User directory path
// 6. Default
// -> Use GetExeDirectory()\User
//
// On Steam builds, we take a simplified approach:
// 1. GetExeDirectory()\portable.txt exists
// -> Use GetExeDirectory()\User
// 2. AppData\Roaming exists
// -> Use AppData\Roaming\Dolphin Emulator (Steam) as the User directory path

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually suggest the Steam builds not use AppData\Roaming at all, and instead rely on Steam user-specific folders. Using folders outside the Steam directory could cause conflicts if multiple Steam users sign into the same OS user. (Sorry I didn't think to say this sooner...)

// 3. Default
// -> Use GetExeDirectory()\User

// Get AppData path in case we need it.
// TODO: Maybe use WIL when it's available?
PWSTR appdata = nullptr;
bool appdata_found =
SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &appdata));

#ifndef STEAM
// Check our registry keys
// TODO: Maybe use WIL when it's available?
HKEY hkey;
Expand Down Expand Up @@ -325,12 +340,6 @@ void SetUserDirectory(std::string custom_path)

local = local != 0 || File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt");

// Get AppData path in case we need it.
// TODO: Maybe use WIL when it's available?
PWSTR appdata = nullptr;
bool appdata_found =
SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &appdata));

// Attempt to check if the old User directory exists in My Documents.
// TODO: Maybe use WIL when it's available?
PWSTR documents = nullptr;
Expand All @@ -340,12 +349,12 @@ void SetUserDirectory(std::string custom_path)
std::optional<std::string> old_user_folder;
if (documents_found)
{
old_user_folder = TStrToUTF8(documents) + DIR_SEP "Dolphin Emulator" DIR_SEP;
old_user_folder = TStrToUTF8(documents) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
}

if (local) // Case 1-2
{
user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
}
else if (configPath) // Case 3
{
Expand All @@ -357,7 +366,7 @@ void SetUserDirectory(std::string custom_path)
}
else if (appdata_found) // Case 5
{
user_path = TStrToUTF8(appdata) + DIR_SEP "Dolphin Emulator" DIR_SEP;
user_path = TStrToUTF8(appdata) + DIR_SEP NORMAL_USER_DIR DIR_SEP;

// Set the UserConfigPath value in the registry for backwards compatibility with older Dolphin
// builds, which will look for the default User directory in Documents. If we set this key,
Expand All @@ -370,15 +379,30 @@ void SetUserDirectory(std::string custom_path)
}
else // Case 6
{
user_path = File::GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
}

CoTaskMemFree(appdata);
CoTaskMemFree(documents);
#else // ifndef STEAM
if (File::Exists(File::GetExeDirectory() + DIR_SEP "portable.txt")) // Case 1
{
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
}
else if (appdata_found) // Case 2
{
user_path = TStrToUTF8(appdata) + DIR_SEP NORMAL_USER_DIR DIR_SEP;
}
else // Case 3
{
user_path = File::GetExeDirectory() + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
}
#endif

CoTaskMemFree(appdata);
#else
if (File::IsDirectory(ROOT_DIR DIR_SEP USERDATA_DIR))
if (File::IsDirectory(ROOT_DIR DIR_SEP EMBEDDED_USER_DIR))
{
user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
user_path = ROOT_DIR DIR_SEP EMBEDDED_USER_DIR DIR_SEP;
}
else
{
Expand Down Expand Up @@ -412,7 +436,7 @@ void SetUserDirectory(std::string custom_path)
std::string exe_path = File::GetExeDirectory();
if (File::Exists(exe_path + DIR_SEP "portable.txt"))
{
user_path = exe_path + DIR_SEP "User" DIR_SEP;
user_path = exe_path + DIR_SEP PORTABLE_USER_DIR DIR_SEP;
}
else if (env_path)
{
Expand All @@ -421,31 +445,31 @@ void SetUserDirectory(std::string custom_path)
#if defined(__APPLE__) || defined(ANDROID)
else
{
user_path = home_path + DOLPHIN_DATA_DIR DIR_SEP;
user_path = home_path + NORMAL_USER_DIR DIR_SEP;
}
#else
else
{
user_path = home_path + "." DOLPHIN_DATA_DIR DIR_SEP;
user_path = home_path + "." NORMAL_USER_DIR DIR_SEP;

if (!File::Exists(user_path))
{
const char* data_home = getenv("XDG_DATA_HOME");
std::string data_path =
std::string(data_home && data_home[0] == '/' ? data_home :
(home_path + ".local" DIR_SEP "share")) +
DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
DIR_SEP NORMAL_USER_DIR DIR_SEP;

const char* config_home = getenv("XDG_CONFIG_HOME");
std::string config_path =
std::string(config_home && config_home[0] == '/' ? config_home :
(home_path + ".config")) +
DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
DIR_SEP NORMAL_USER_DIR DIR_SEP;

const char* cache_home = getenv("XDG_CACHE_HOME");
std::string cache_path =
std::string(cache_home && cache_home[0] == '/' ? cache_home : (home_path + ".cache")) +
DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
DIR_SEP NORMAL_USER_DIR DIR_SEP;

File::SetUserPath(D_USER_IDX, data_path);
File::SetUserPath(D_CONFIG_IDX, config_path);
Expand Down