@ -3,6 +3,7 @@
// Refer to the license.txt file included.
# include <sstream>
# include <unordered_map>
# include "common/assert.h"
# include "common/common_funcs.h"
# include "common/common_paths.h"
@ -681,67 +682,68 @@ std::string GetSysDirectory() {
// Returns a string with a yuzu data dir or file in the user's home
// directory. To be used in "multi-user" mode (that is, installed).
const std : : string & GetUserPath ( const unsigned int DirIDX , const std : : string & newPath ) {
static std : : string paths [ NUM_PATH_INDICES ] ;
const std : : string & GetUserPath ( UserPath path , const std : : string & new_path ) {
static std : : unordered_map < UserPath , std : : string > paths ;
auto & user_path = paths [ UserPath : : UserDir ] ;
// Set up all paths and files on the first run
if ( paths[ D_USER_IDX ] . empty ( ) ) {
if ( user_ path. empty ( ) ) {
# ifdef _WIN32
paths[ D_USER_IDX ] = GetExeDirectory ( ) + DIR_SEP USERDATA_DIR DIR_SEP ;
if ( ! FileUtil : : IsDirectory ( paths[ D_USER_IDX ] ) ) {
paths[ D_USER_IDX ] = AppDataRoamingDirectory ( ) + DIR_SEP EMU_DATA_DIR DIR_SEP ;
user_ path = GetExeDirectory ( ) + DIR_SEP USERDATA_DIR DIR_SEP ;
if ( ! FileUtil : : IsDirectory ( user_ path) ) {
user_ path = AppDataRoamingDirectory ( ) + DIR_SEP EMU_DATA_DIR DIR_SEP ;
} else {
LOG_INFO ( Common_Filesystem , " Using the local user directory " ) ;
}
paths [D_CONFIG_IDX ] = paths [ D_USER_IDX ] + CONFIG_DIR DIR_SEP ;
paths [D_CACHE_IDX ] = paths [ D_USER_IDX ] + CACHE_DIR DIR_SEP ;
paths .emplace ( UserPath : : ConfigDir , user_path + CONFIG_DIR DIR_SEP ) ;
paths .emplace ( UserPath : : CacheDir , user_path + CACHE_DIR DIR_SEP ) ;
# else
if ( FileUtil : : Exists ( ROOT_DIR DIR_SEP USERDATA_DIR ) ) {
paths[ D_USER_IDX ] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP ;
paths [D_CONFIG_IDX ] = paths [ D_USER_IDX ] + CONFIG_DIR DIR_SEP ;
paths [D_CACHE_IDX ] = paths [ D_USER_IDX ] + CACHE_DIR DIR_SEP ;
user_ path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP ;
paths .emplace ( UserPath : : ConfigDir , user_path + CONFIG_DIR DIR_SEP ) ;
paths .emplace ( UserPath : : CacheDir , user_path + CACHE_DIR DIR_SEP ) ;
} else {
std : : string data_dir = GetUserDirectory ( " XDG_DATA_HOME " ) ;
std : : string config_dir = GetUserDirectory ( " XDG_CONFIG_HOME " ) ;
std : : string cache_dir = GetUserDirectory ( " XDG_CACHE_HOME " ) ;
paths[ D_USER_IDX ] = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ;
paths [D_CONFIG_IDX ] = config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ;
paths [D_CACHE_IDX ] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ;
user_ path = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ;
paths .emplace ( UserPath : : ConfigDir , config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ) ;
paths .emplace ( UserPath : : CacheDir , cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP ) ;
}
# endif
paths [D_SDMC_IDX ] = paths [ D_USER_IDX ] + SDMC_DIR DIR_SEP ;
paths [D_NAND_IDX ] = paths [ D_USER_IDX ] + NAND_DIR DIR_SEP ;
paths [D_SYSDATA_IDX ] = paths [ D_USER_IDX ] + SYSDATA_DIR DIR_SEP ;
paths .emplace ( UserPath : : SDMCDir , user_path + SDMC_DIR DIR_SEP ) ;
paths .emplace ( UserPath : : NANDDir , user_path + NAND_DIR DIR_SEP ) ;
paths .emplace ( UserPath : : SysDataDir , user_path + SYSDATA_DIR DIR_SEP ) ;
// TODO: Put the logs in a better location for each OS
paths [D_LOGS_IDX ] = paths [ D_USER_IDX ] + LOG_DIR DIR_SEP ;
paths .emplace ( UserPath : : LogDir , user_path + LOG_DIR DIR_SEP ) ;
}
if ( ! new P ath. empty ( ) ) {
if ( ! FileUtil : : IsDirectory ( new P ath) ) {
LOG_ERROR ( Common_Filesystem , " Invalid path specified {} " , new P ath) ;
return paths [ DirIDX ] ;
if ( ! new _p ath. empty ( ) ) {
if ( ! FileUtil : : IsDirectory ( new _p ath) ) {
LOG_ERROR ( Common_Filesystem , " Invalid path specified {} " , new _p ath) ;
return paths [ path ] ;
} else {
paths [ DirIDX] = newP ath;
paths [ path] = new_p ath;
}
switch ( DirIDX ) {
case D_ROOT_IDX :
paths[ D_USER_IDX ] = paths [ D_ROOT_IDX ] + DIR_SEP ;
switch ( path ) {
case UserPath : : RootDir :
user_path = paths [ UserPath : : RootDir ] + DIR_SEP ;
break ;
case D_USER_IDX :
paths[ D_USER_IDX ] = paths [ D_ROOT_IDX ] + DIR_SEP ;
paths [ D_CONFIG_IDX] = paths [ D_USER_IDX ] + CONFIG_DIR DIR_SEP ;
paths [ D_CACHE_IDX] = paths [ D_USER_IDX ] + CACHE_DIR DIR_SEP ;
paths [ D_SDMC_IDX] = paths [ D_USER_IDX ] + SDMC_DIR DIR_SEP ;
paths [ D_NAND_IDX] = paths [ D_USER_IDX ] + NAND_DIR DIR_SEP ;
case UserPath : : UserDir :
user_path = paths [ UserPath : : RootDir ] + DIR_SEP ;
paths [ UserPath: : ConfigDir ] = user_path + CONFIG_DIR DIR_SEP ;
paths [ UserPath: : CacheDir ] = user_path + CACHE_DIR DIR_SEP ;
paths [ UserPath: : SDMCDir ] = user_path + SDMC_DIR DIR_SEP ;
paths [ UserPath: : NANDDir ] = user_path + NAND_DIR DIR_SEP ;
break ;
}
}
return paths [ DirIDX ] ;
return paths [ path ] ;
}
size_t WriteStringToFile ( bool text_file , const std : : string & str , const char * filename ) {