Add ability to save/read files based on XDG specification

Fix some \\ in paths to be /
This commit is contained in:
Andrew Udvare 2022-08-30 11:48:47 -04:00
parent 15b71c57dd
commit 730a3791a1
No known key found for this signature in database
GPG key ID: 1AFD9AFC120C26DD
30 changed files with 254 additions and 135 deletions

View file

@ -50,6 +50,13 @@ option(ENABLE_OPENGL "Enables the OpenGL backend" ON)
option(ENABLE_VULKAN "Enables the Vulkan backend" ON) option(ENABLE_VULKAN "Enables the Vulkan backend" ON)
option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON) option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON)
if (UNIX)
option(ENABLE_XDG_DIRS "Enable storage according to XDG specification" ON)
endif()
if (SYSTEM_DATA_PATH)
add_compile_definitions(SYSTEM_DATA_PATH=\"${SYSTEM_DATA_PATH}\")
endif()
# input backends # input backends
if (WIN32) if (WIN32)
option(ENABLE_XINPUT "Enables the usage of XInput" ON) option(ENABLE_XINPUT "Enables the usage of XInput" ON)
@ -125,6 +132,10 @@ if (ENABLE_CUBEB)
add_compile_definitions("HAS_CUBEB=1") add_compile_definitions("HAS_CUBEB=1")
endif() endif()
if (ENABLE_XDG_DIRS)
add_compile_definitions(XDG)
endif()
add_subdirectory("dependencies/ih264d") add_subdirectory("dependencies/ih264d")
find_package(ZArchive) find_package(ZArchive)

View file

@ -424,7 +424,7 @@ OnlineValidator Account::ValidateOnlineFiles() const
{ {
OnlineValidator result{}; OnlineValidator result{};
const auto otp = ActiveSettings::GetPath("otp.bin"); const auto otp = ActiveSettings::GetDataPath("otp.bin");
if (!fs::exists(otp)) if (!fs::exists(otp))
result.otp = OnlineValidator::FileState::Missing; result.otp = OnlineValidator::FileState::Missing;
else if (fs::file_size(otp) != 1024) else if (fs::file_size(otp) != 1024)
@ -432,7 +432,7 @@ OnlineValidator Account::ValidateOnlineFiles() const
else else
result.otp = OnlineValidator::FileState::Ok; result.otp = OnlineValidator::FileState::Ok;
const auto seeprom = ActiveSettings::GetPath("seeprom.bin"); const auto seeprom = ActiveSettings::GetDataPath("seeprom.bin");
if (!fs::exists(seeprom)) if (!fs::exists(seeprom))
result.seeprom = OnlineValidator::FileState::Missing; result.seeprom = OnlineValidator::FileState::Missing;
else if (fs::file_size(seeprom) != 512) else if (fs::file_size(seeprom) != 512)

View file

@ -289,7 +289,7 @@ uint32 loadSharedData()
for (sint32 i = 0; i < sizeof(shareddataDef) / sizeof(shareddataDef[0]); i++) for (sint32 i = 0; i < sizeof(shareddataDef) / sizeof(shareddataDef[0]); i++)
{ {
bool existsInMLC = fs::exists(ActiveSettings::GetMlcPath(shareddataDef[i].mlcPath)); bool existsInMLC = fs::exists(ActiveSettings::GetMlcPath(shareddataDef[i].mlcPath));
bool existsInResources = fs::exists(ActiveSettings::GetPath(shareddataDef[i].resourcePath)); bool existsInResources = fs::exists(ActiveSettings::GetSystemDataPath(shareddataDef[i].resourcePath));
if (!existsInMLC && !existsInResources) if (!existsInMLC && !existsInResources)
{ {
@ -314,7 +314,7 @@ uint32 loadSharedData()
// alternatively fall back to our shared fonts // alternatively fall back to our shared fonts
if (!fontFile) if (!fontFile)
{ {
path = ActiveSettings::GetPath(shareddataDef[i].resourcePath); path = ActiveSettings::GetSystemDataPath(shareddataDef[i].resourcePath);
fontFile = FileStream::openFile2(path); fontFile = FileStream::openFile2(path);
} }
if (!fontFile) if (!fontFile)
@ -340,7 +340,7 @@ uint32 loadSharedData()
return memory_getVirtualOffsetFromPointer(dataWritePtr); return memory_getVirtualOffsetFromPointer(dataWritePtr);
} }
// alternative method: load RAM dump // alternative method: load RAM dump
const auto path = ActiveSettings::GetPath("shareddata.bin"); const auto path = ActiveSettings::GetSystemDataPath("shareddata.bin");
FileStream* ramDumpFile = FileStream::openFile2(path); FileStream* ramDumpFile = FileStream::openFile2(path);
if (ramDumpFile) if (ramDumpFile)
{ {

View file

@ -59,7 +59,7 @@ void KeyCache_Prepare()
sKeyCachePrepared = true; sKeyCachePrepared = true;
g_keyCache.clear(); g_keyCache.clear();
// load keys // load keys
auto keysPath = ActiveSettings::GetPath("keys.txt"); auto keysPath = ActiveSettings::GetConfigPath("keys.txt");
FileStream* fs_keys = FileStream::openFile2(keysPath); FileStream* fs_keys = FileStream::openFile2(keysPath);
if( !fs_keys ) if( !fs_keys )
{ {

View file

@ -180,12 +180,12 @@ void gameProfile_load()
bool GameProfile::Load(uint64_t title_id) bool GameProfile::Load(uint64_t title_id)
{ {
auto gameProfilePath = ActiveSettings::GetPath("gameProfiles/{:016x}.ini", title_id); auto gameProfilePath = ActiveSettings::GetDataPath("gameProfiles/{:016x}.ini", title_id);
std::optional<std::vector<uint8>> profileContents = FileStream::LoadIntoMemory(gameProfilePath); std::optional<std::vector<uint8>> profileContents = FileStream::LoadIntoMemory(gameProfilePath);
if (!profileContents) if (!profileContents)
{ {
gameProfilePath = ActiveSettings::GetPath("gameProfiles/default/{:016x}.ini", title_id); gameProfilePath = ActiveSettings::GetSystemDataPath("gameProfiles/default/{:016x}.ini", title_id);
profileContents = FileStream::LoadIntoMemory(gameProfilePath); profileContents = FileStream::LoadIntoMemory(gameProfilePath);
if (!profileContents) if (!profileContents)
return false; return false;
@ -276,7 +276,7 @@ bool GameProfile::Load(uint64_t title_id)
void GameProfile::Save(uint64_t title_id) void GameProfile::Save(uint64_t title_id)
{ {
auto gameProfilePath = ActiveSettings::GetPath("gameProfiles/{:016x}.ini", title_id); auto gameProfilePath = ActiveSettings::GetConfigPath("gameProfiles/{:016x}.ini", title_id);
FileStream* fs = FileStream::createFile2(gameProfilePath); FileStream* fs = FileStream::createFile2(gameProfilePath);
if (!fs) if (!fs)
{ {

View file

@ -84,7 +84,7 @@ void graphicPack_loadAll()
{ {
// recursively iterate all directories in graphicPacks/ folder // recursively iterate all directories in graphicPacks/ folder
std::wstring graphicPackRelativePath; std::wstring graphicPackRelativePath;
graphicPack_scanForGFXPackFolders(ActiveSettings::GetPath("graphicPacks/"), graphicPackRelativePath); graphicPack_scanForGFXPackFolders(ActiveSettings::GetDataPath("graphicPacks/"), graphicPackRelativePath);
} }
void graphicPack_activateForCurrentTitle(uint64 titleId) void graphicPack_activateForCurrentTitle(uint64 titleId)

View file

@ -198,17 +198,17 @@ void LatteShaderCache_load()
LatteShaderCache_initCompileQueue(); LatteShaderCache_initCompileQueue();
// create directories // create directories
std::error_code ec; std::error_code ec;
fs::create_directories(ActiveSettings::GetPath("shaderCache/transferable"), ec); fs::create_directories(ActiveSettings::GetCachePath("shaderCache/transferable"), ec);
fs::create_directories(ActiveSettings::GetPath("shaderCache/precompiled"), ec); fs::create_directories(ActiveSettings::GetCachePath("shaderCache/precompiled"), ec);
// initialize renderer specific caches // initialize renderer specific caches
if (g_renderer->GetType() == RendererAPI::Vulkan) if (g_renderer->GetType() == RendererAPI::Vulkan)
RendererShaderVk::ShaderCacheLoading_begin(cacheTitleId); RendererShaderVk::ShaderCacheLoading_begin(cacheTitleId);
else if (g_renderer->GetType() == RendererAPI::OpenGL) else if (g_renderer->GetType() == RendererAPI::OpenGL)
RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId);
// get cache file name // get cache file name
const auto pathGeneric = ActiveSettings::GetPath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId); const auto pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId);
const auto pathGenericPre1_25_0 = ActiveSettings::GetPath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.0 const auto pathGenericPre1_25_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.0
const auto pathGenericPre1_16_0 = ActiveSettings::GetPath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0 const auto pathGenericPre1_16_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0
LatteShaderCache_handleDeprecatedCacheFiles(pathGeneric, pathGenericPre1_25_0, pathGenericPre1_16_0); LatteShaderCache_handleDeprecatedCacheFiles(pathGeneric, pathGenericPre1_25_0, pathGenericPre1_16_0);
// calculate extraVersion for transferable and precompiled shader cache // calculate extraVersion for transferable and precompiled shader cache

View file

@ -279,7 +279,7 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
{ {
const uint32 cacheMagic = GeneratePrecompiledCacheId(); const uint32 cacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId); const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId);
const std::wstring cachePath = ActiveSettings::GetPath("shaderCache/precompiled/{}", cacheFilename).generic_wstring(); const std::wstring cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename).generic_wstring();
g_programBinaryCache = FileCache::Open(cachePath, true, cacheMagic); g_programBinaryCache = FileCache::Open(cachePath, true, cacheMagic);
if (g_programBinaryCache == nullptr) if (g_programBinaryCache == nullptr)
cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename); cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename);

View file

@ -133,7 +133,7 @@ void Renderer::SaveScreenshot(const std::vector<uint8>& rgb_data, int width, int
// save to png file // save to png file
if (save_screenshot) if (save_screenshot)
{ {
fs::path screendir = ActiveSettings::GetPath("screenshots"); fs::path screendir = ActiveSettings::GetDataPath("screenshots");
if (!fs::exists(screendir)) if (!fs::exists(screendir))
fs::create_directory(screendir); fs::create_directory(screendir);

View file

@ -456,7 +456,7 @@ void RendererShaderVk::ShaderCacheLoading_begin(uint64 cacheTitleId)
} }
uint32 spirvCacheMagic = GeneratePrecompiledCacheId(); uint32 spirvCacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_spirv.bin", cacheTitleId); const std::string cacheFilename = fmt::format("{:016x}_spirv.bin", cacheTitleId);
const std::wstring cachePath = ActiveSettings::GetPath("shaderCache/precompiled/{}", cacheFilename).generic_wstring(); const std::wstring cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename).generic_wstring();
s_spirvCache = FileCache::Open(cachePath, true, spirvCacheMagic); s_spirvCache = FileCache::Open(cachePath, true, spirvCacheMagic);
if (s_spirvCache == nullptr) if (s_spirvCache == nullptr)
cemuLog_log(LogType::Force, "Unable to open SPIR-V cache {}", cacheFilename); cemuLog_log(LogType::Force, "Unable to open SPIR-V cache {}", cacheFilename);

View file

@ -32,15 +32,13 @@ VulkanPipelineStableCache& VulkanPipelineStableCache::GetInstance()
uint32 VulkanPipelineStableCache::BeginLoading(uint64 cacheTitleId) uint32 VulkanPipelineStableCache::BeginLoading(uint64 cacheTitleId)
{ {
std::error_code ec; std::error_code ec;
fs::create_directories(ActiveSettings::GetPath("shaderCache/transferable"), ec); fs::create_directories(ActiveSettings::GetCachePath("shaderCache/transferable"), ec);
const auto pathCacheFile = ActiveSettings::GetPath("shaderCache/transferable/{:016x}_vkpipeline.bin", cacheTitleId); const auto pathCacheFile = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_vkpipeline.bin", cacheTitleId);
// init cache loader state // init cache loader state
g_vkCacheState.pipelineLoadIndex = 0; g_vkCacheState.pipelineLoadIndex = 0;
g_vkCacheState.pipelineMaxFileIndex = 0; g_vkCacheState.pipelineMaxFileIndex = 0;
g_vkCacheState.pipelinesLoaded = 0; g_vkCacheState.pipelinesLoaded = 0;
g_vkCacheState.pipelinesQueued = 0; g_vkCacheState.pipelinesQueued = 0;
// start async compilation threads // start async compilation threads
m_compilationCount.store(0); m_compilationCount.store(0);
m_compilationQueue.clear(); m_compilationQueue.clear();

View file

@ -2294,7 +2294,7 @@ void VulkanRenderer::WaitCommandBufferFinished(uint64 commandBufferId)
void VulkanRenderer::PipelineCacheSaveThread(size_t cache_size) void VulkanRenderer::PipelineCacheSaveThread(size_t cache_size)
{ {
const auto dir = ActiveSettings::GetPath("shaderCache/driver/vk"); const auto dir = ActiveSettings::GetCachePath("shaderCache/driver/vk");
if (!fs::exists(dir)) if (!fs::exists(dir))
{ {
try try
@ -2371,7 +2371,7 @@ void VulkanRenderer::PipelineCacheSaveThread(size_t cache_size)
void VulkanRenderer::CreatePipelineCache() void VulkanRenderer::CreatePipelineCache()
{ {
std::vector<uint8_t> cacheData; std::vector<uint8_t> cacheData;
const auto dir = ActiveSettings::GetPath("shaderCache/driver/vk"); const auto dir = ActiveSettings::GetCachePath("shaderCache/driver/vk");
if (fs::exists(dir)) if (fs::exists(dir))
{ {
const auto filename = dir / fmt::format("{:016x}.bin", CafeSystem::GetForegroundTitleId()); const auto filename = dir / fmt::format("{:016x}.bin", CafeSystem::GetForegroundTitleId());

View file

@ -409,7 +409,7 @@ void memory_writeDumpFile(uint32 startAddr, uint32 size, const fs::path& path)
void memory_createDump() void memory_createDump()
{ {
const uint32 pageSize = MemMapper::GetPageSize(); const uint32 pageSize = MemMapper::GetPageSize();
fs::path path = ActiveSettings::GetPath("dump/ramDump{:}", (uint32)time(nullptr)); fs::path path = ActiveSettings::GetDataPath("dump/ramDump{:}", (uint32)time(nullptr));
fs::create_directories(path); fs::create_directories(path);
for (auto& itr : g_mmuRanges) for (auto& itr : g_mmuRanges)

View file

@ -563,7 +563,7 @@ void iosuCrypto_loadSSLCertificates()
void iosuCrypto_init() void iosuCrypto_init()
{ {
// load OTP dump // load OTP dump
if (std::ifstream otp_file(ActiveSettings::GetPath("otp.bin"), std::ifstream::in | std::ios::binary); otp_file.is_open()) if (std::ifstream otp_file(ActiveSettings::GetDataPath("otp.bin"), std::ifstream::in | std::ios::binary); otp_file.is_open())
{ {
otp_file.seekg(0, std::ifstream::end); otp_file.seekg(0, std::ifstream::end);
const auto length = otp_file.tellg(); const auto length = otp_file.tellg();
@ -586,7 +586,7 @@ void iosuCrypto_init()
hasOtpMem = false; hasOtpMem = false;
} }
if (std::ifstream seeprom_file(ActiveSettings::GetPath("seeprom.bin"), std::ifstream::in | std::ios::binary); seeprom_file.is_open()) if (std::ifstream seeprom_file(ActiveSettings::GetDataPath("seeprom.bin"), std::ifstream::in | std::ios::binary); seeprom_file.is_open())
{ {
seeprom_file.seekg(0, std::ifstream::end); seeprom_file.seekg(0, std::ifstream::end);
const auto length = seeprom_file.tellg(); const auto length = seeprom_file.tellg();
@ -630,13 +630,13 @@ sint32 iosuCrypt_checkRequirementsForOnlineMode(std::wstring& additionalErrorInf
{ {
std::error_code ec; std::error_code ec;
// check if otp.bin is present // check if otp.bin is present
const auto otp_file = ActiveSettings::GetPath("otp.bin"); const auto otp_file = ActiveSettings::GetDataPath("otp.bin");
if(!fs::exists(otp_file, ec)) if(!fs::exists(otp_file, ec))
return IOS_CRYPTO_ONLINE_REQ_OTP_MISSING; return IOS_CRYPTO_ONLINE_REQ_OTP_MISSING;
if(fs::file_size(otp_file, ec) != 1024) if(fs::file_size(otp_file, ec) != 1024)
return IOS_CRYPTO_ONLINE_REQ_OTP_CORRUPTED; return IOS_CRYPTO_ONLINE_REQ_OTP_CORRUPTED;
// check if seeprom.bin is present // check if seeprom.bin is present
const auto seeprom_file = ActiveSettings::GetPath("seeprom.bin"); const auto seeprom_file = ActiveSettings::GetDataPath("seeprom.bin");
if (!fs::exists(seeprom_file, ec)) if (!fs::exists(seeprom_file, ec))
return IOS_CRYPTO_ONLINE_REQ_SEEPROM_MISSING; return IOS_CRYPTO_ONLINE_REQ_SEEPROM_MISSING;
if (fs::file_size(seeprom_file, ec) != 512) if (fs::file_size(seeprom_file, ec) != 512)

View file

@ -2122,7 +2122,7 @@ void RPLLoader_LoadDependency(rplDependency_t* dependency)
// attempt to load rpl from Cemu's /cafeLibs/ directory // attempt to load rpl from Cemu's /cafeLibs/ directory
if (ActiveSettings::LoadSharedLibrariesEnabled()) if (ActiveSettings::LoadSharedLibrariesEnabled())
{ {
const auto filePath = ActiveSettings::GetPath("cafeLibs/{}", dependency->filepath); const auto filePath = ActiveSettings::GetDataPath("cafeLibs/{}", dependency->filepath);
auto fileData = FileStream::LoadIntoMemory(filePath); auto fileData = FileStream::LoadIntoMemory(filePath);
if (fileData) if (fileData)
{ {

View file

@ -107,7 +107,7 @@ namespace coreinit
return; return;
std::error_code ec; std::error_code ec;
const auto path = ActiveSettings::GetPath("sdcard/"); const auto path = ActiveSettings::GetDataPath("sdcard/");
fs::create_directories(path, ec); fs::create_directories(path, ec);
FSCDeviceHostFS_Mount("/vol/external01", path.generic_wstring().c_str() , FSC_PRIORITY_BASE); FSCDeviceHostFS_Mount("/vol/external01", path.generic_wstring().c_str() , FSC_PRIORITY_BASE);
@ -140,7 +140,7 @@ namespace coreinit
return FS_RESULT::ERR_PLACEHOLDER; return FS_RESULT::ERR_PLACEHOLDER;
std::error_code ec; std::error_code ec;
const auto path = ActiveSettings::GetPath("sdcard/"); const auto path = ActiveSettings::GetDataPath("sdcard/");
fs::create_directories(path, ec); fs::create_directories(path, ec);
if (!FSCDeviceHostFS_Mount(mountPathOut, path.generic_wstring().c_str(), FSC_PRIORITY_BASE)) if (!FSCDeviceHostFS_Mount(mountPathOut, path.generic_wstring().c_str(), FSC_PRIORITY_BASE))
return FS_RESULT::ERR_PLACEHOLDER; return FS_RESULT::ERR_PLACEHOLDER;

View file

@ -98,7 +98,7 @@ void cemuLog_createLogFile(bool triggeredByCrash)
if (LogContext.file_stream.is_open()) if (LogContext.file_stream.is_open())
return; return;
const auto path = ActiveSettings::GetPath("log.txt"); const auto path = ActiveSettings::GetDataPath("log.txt");
LogContext.file_stream.open(path, std::ios::out); LogContext.file_stream.open(path, std::ios::out);
if (LogContext.file_stream.fail()) if (LogContext.file_stream.fail())
{ {

View file

@ -72,7 +72,7 @@ bool CreateMiniDump(CrashDump dump, EXCEPTION_POINTERS* pep)
if (dump == CrashDump::Disabled) if (dump == CrashDump::Disabled)
return true; return true;
fs::path p = ActiveSettings::GetPath("crashdump"); fs::path p = ActiveSettings::GetDataPath("crashdump");
std::error_code ec; std::error_code ec;
fs::create_directories(p, ec); fs::create_directories(p, ec);
@ -367,11 +367,11 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context)
const auto temp_time = std::chrono::system_clock::to_time_t(now); const auto temp_time = std::chrono::system_clock::to_time_t(now);
const auto& time = *std::gmtime(&temp_time); const auto& time = *std::gmtime(&temp_time);
fs::path p = ActiveSettings::GetPath("crashdump"); fs::path p = ActiveSettings::GetDataPath("crashdump");
p /= fmt::format("log_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.txt", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_year, time.tm_hour, time.tm_min, time.tm_sec); p /= fmt::format("log_{:04d}{:02d}{:02d}_{:02d}{:02d}{:02d}.txt", 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday, time.tm_year, time.tm_hour, time.tm_min, time.tm_sec);
std::error_code ec; std::error_code ec;
fs::copy_file(ActiveSettings::GetPath("log.txt"), p, ec); fs::copy_file(ActiveSettings::GetDataPath("log.txt"), p, ec);
} }
exit(0); exit(0);

View file

@ -18,7 +18,7 @@ void ActiveSettings::LoadOnce()
s_path = s_full_path.parent_path(); s_path = s_full_path.parent_path();
s_filename = s_full_path.filename(); s_filename = s_full_path.filename();
g_config.SetFilename(GetPath("settings.xml").generic_wstring()); g_config.SetFilename(GetConfigPath("settings.xml").generic_wstring());
g_config.Load(); g_config.Load();
std::wstring additionalErrorInfo; std::wstring additionalErrorInfo;
@ -220,8 +220,59 @@ fs::path ActiveSettings::GetMlcPath()
return GetDefaultMLCPath(); return GetDefaultMLCPath();
} }
fs::path ActiveSettings::GetDefaultMLCPath() #ifdef XDG
std::string ActiveSettings::GetXDGPath(const char* envVar, const std::string& defaultValue)
{ {
return GetPath("mlc01"); auto raw_value = std::getenv(envVar);
return !raw_value || std::strlen(raw_value) == 0 ? defaultValue : std::string(raw_value);
}
#endif
fs::path ActiveSettings::GetConfigPath()
{
#ifdef XDG
auto config_home = GetXDGPath("XDG_CONFIG_HOME", fmt::format("{}/.config", std::getenv("HOME")));
auto dir = fs::path(fmt::format("{}/cemu", config_home));
if (!fs::exists(dir))
fs::create_directories(dir);
return dir;
#endif
return s_full_path;
} }
fs::path ActiveSettings::GetCachePath()
{
#ifdef XDG
auto config_home = GetXDGPath("XDG_CACHE_HOME", fmt::format("{}/.cache", std::getenv("HOME")));
auto dir = fs::path(fmt::format("{}/cemu", config_home));
if (!fs::exists(dir))
fs::create_directories(dir);
return dir;
#endif
return s_full_path;
}
fs::path ActiveSettings::GetDataPath()
{
#ifdef XDG
auto config_home = GetXDGPath("XDG_DATA_HOME", fmt::format("{}/.local/share", std::getenv("HOME")));
auto dir = fs::path(fmt::format("{}/cemu", config_home));
if (!fs::exists(dir))
fs::create_directories(dir);
return dir;
#endif
return s_full_path;
}
fs::path ActiveSettings::GetSystemDataPath()
{
#ifdef SYSTEM_DATA_PATH
return fs::path(SYSTEM_DATA_PATH);
#endif
return s_full_path;
}
fs::path ActiveSettings::GetDefaultMLCPath()
{
return GetDataPath("mlc01");
}

View file

@ -13,6 +13,11 @@ public:
[[nodiscard]] static fs::path GetFilename() { return s_filename; } [[nodiscard]] static fs::path GetFilename() { return s_filename; }
[[nodiscard]] static fs::path GetMlcPath(); [[nodiscard]] static fs::path GetMlcPath();
[[nodiscard]] static fs::path GetCachePath();
[[nodiscard]] static fs::path GetConfigPath();
[[nodiscard]] static fs::path GetDataPath();
[[nodiscard]] static fs::path GetSystemDataPath();
[[nodiscard]] static std::string GetXDGPath (const char* envVar, const std::string& defaultValue);
[[nodiscard]] static fs::path GetPath(std::string_view p) [[nodiscard]] static fs::path GetPath(std::string_view p)
{ {
@ -57,6 +62,62 @@ public:
return GetMlcPath() / fmt::format(format, std::forward<TArgs>(args)...); return GetMlcPath() / fmt::format(format, std::forward<TArgs>(args)...);
} }
template <typename ...TArgs>
[[nodiscard]] static fs::path GetCachePath(std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetCachePath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template <typename ...TArgs>
[[nodiscard]] static fs::path GetCachePath(std::wstring_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetCachePath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template <typename ...TArgs>
[[nodiscard]] static fs::path GetConfigPath(std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetConfigPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template <typename ...TArgs>
[[nodiscard]] static fs::path GetConfigPath(std::wstring_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetConfigPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template <typename ...TArgs>
[[nodiscard]] static fs::path GetDataPath(std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetDataPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template <typename ...TArgs>
[[nodiscard]] static fs::path GetDataPath(std::wstring_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetDataPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template<typename... TArgs>
[[nodiscard]] static fs::path GetSystemDataPath (std::string_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetSystemDataPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
template<typename... TArgs>
[[nodiscard]] static fs::path GetSystemDataPath (std::wstring_view format, TArgs&&... args)
{
cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\'));
return GetSystemDataPath() / fmt::format(format, std::forward<TArgs>(args)...);
}
// get mlc path to default cemu root dir/mlc01 // get mlc path to default cemu root dir/mlc01
[[nodiscard]] static fs::path GetDefaultMLCPath(); [[nodiscard]] static fs::path GetDefaultMLCPath();
@ -126,4 +187,3 @@ private:
inline static bool s_has_required_online_files = false; inline static bool s_has_required_online_files = false;
}; };

View file

@ -115,7 +115,7 @@ bool CemuApp::OnInit()
Bind(wxEVT_ACTIVATE_APP, &CemuApp::ActivateApp, this); Bind(wxEVT_ACTIVATE_APP, &CemuApp::ActivateApp, this);
if (!TestWriteAccess(ActiveSettings::GetPath())) if (!TestWriteAccess(ActiveSettings::GetConfigPath()))
wxMessageBox(_("Cemu can't write to its directory.\nPlease move it to a different location or run Cemu as administrator!"), _("Warning"), wxOK | wxCENTRE | wxICON_EXCLAMATION, nullptr); wxMessageBox(_("Cemu can't write to its directory.\nPlease move it to a different location or run Cemu as administrator!"), _("Warning"), wxOK | wxCENTRE | wxICON_EXCLAMATION, nullptr);
auto& config = GetConfig(); auto& config = GetConfig();
@ -183,7 +183,7 @@ int CemuApp::FilterEvent(wxEvent& event)
std::vector<const wxLanguageInfo*> CemuApp::GetAvailableLanguages() std::vector<const wxLanguageInfo*> CemuApp::GetAvailableLanguages()
{ {
const auto path = ActiveSettings::GetPath("resources"); const auto path = ActiveSettings::GetSystemDataPath("resources");
if (!exists(path)) if (!exists(path))
return {}; return {};
@ -308,11 +308,11 @@ void CemuApp::CreateDefaultFiles(bool first_start)
// cemu directories // cemu directories
try try
{ {
const auto controllerProfileFolder = GetCemuPath(L"controllerProfiles").ToStdWstring(); const auto controllerProfileFolder = ActiveSettings::GetConfigPath(L"controllerProfiles").generic_wstring();
if (!fs::exists(controllerProfileFolder)) if (!fs::exists(controllerProfileFolder))
fs::create_directories(controllerProfileFolder); fs::create_directories(controllerProfileFolder);
const auto memorySearcherFolder = GetCemuPath(L"memorySearcher").ToStdWstring(); const auto memorySearcherFolder = ActiveSettings::GetConfigPath(L"memorySearcher").generic_wstring();
if (!fs::exists(memorySearcherFolder)) if (!fs::exists(memorySearcherFolder))
fs::create_directories(memorySearcherFolder); fs::create_directories(memorySearcherFolder);
} }
@ -406,4 +406,3 @@ extern "C"
return *static_cast<CemuApp*>(wxApp::GetInstance()); return *static_cast<CemuApp*>(wxApp::GetInstance());
}; };
} }

View file

@ -137,7 +137,7 @@ ChecksumTool::ChecksumTool(wxWindow* parent, wxTitleManagerList::TitleEntry& ent
const auto title_id_str = fmt::format("{:016x}", m_json_entry.title_id); const auto title_id_str = fmt::format("{:016x}", m_json_entry.title_id);
const auto default_file = fmt::format("{}_v{}.json", title_id_str, m_info.GetAppTitleVersion()); const auto default_file = fmt::format("{}_v{}.json", title_id_str, m_info.GetAppTitleVersion());
const auto checksum_path = ActiveSettings::GetPath("resources/checksums/{}", default_file); const auto checksum_path = ActiveSettings::GetDataPath("resources/checksums/{}", default_file);
if (exists(checksum_path)) if (exists(checksum_path))
m_verify_online->Enable(); m_verify_online->Enable();
} }
@ -189,7 +189,7 @@ void ChecksumTool::LoadOnlineData() const
std::string latest_commit; std::string latest_commit;
const auto checksum_path = ActiveSettings::GetPath("resources/checksums"); const auto checksum_path = ActiveSettings::GetDataPath("resources/checksums");
if (exists(checksum_path)) if (exists(checksum_path))
{ {
std::string current_commit; std::string current_commit;
@ -600,7 +600,7 @@ void ChecksumTool::OnVerifyOnline(wxCommandEvent& event)
const auto title_id_str = fmt::format("{:016x}", m_json_entry.title_id); const auto title_id_str = fmt::format("{:016x}", m_json_entry.title_id);
const auto default_file = fmt::format("{}_v{}.json", title_id_str, m_info.GetAppTitleVersion()); const auto default_file = fmt::format("{}_v{}.json", title_id_str, m_info.GetAppTitleVersion());
const auto checksum_path = ActiveSettings::GetPath("resources/checksums/{}", default_file); const auto checksum_path = ActiveSettings::GetDataPath("resources/checksums/{}", default_file);
if(!exists(checksum_path)) if(!exists(checksum_path))
return; return;

View file

@ -67,7 +67,7 @@ bool DownloadGraphicPacksWindow::curlDownloadFile(const char *url, curlDownloadF
bool checkGraphicPackDownloadedVersion(const char* nameVersion, bool& hasVersionFile) bool checkGraphicPackDownloadedVersion(const char* nameVersion, bool& hasVersionFile)
{ {
hasVersionFile = false; hasVersionFile = false;
const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/version.txt"); const auto path = ActiveSettings::GetDataPath("graphicPacks/downloadedGraphicPacks/version.txt");
std::unique_ptr<FileStream> file(FileStream::openFile2(path)); std::unique_ptr<FileStream> file(FileStream::openFile2(path));
std::string versionInFile; std::string versionInFile;
@ -80,7 +80,7 @@ bool checkGraphicPackDownloadedVersion(const char* nameVersion, bool& hasVersion
void createGraphicPackDownloadedVersionFile(const char* nameVersion) void createGraphicPackDownloadedVersionFile(const char* nameVersion)
{ {
const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/version.txt"); const auto path = ActiveSettings::GetDataPath("graphicPacks/downloadedGraphicPacks/version.txt");
std::unique_ptr<FileStream> file(FileStream::createFile2(path)); std::unique_ptr<FileStream> file(FileStream::createFile2(path));
if (file) if (file)
file->writeString(nameVersion); file->writeString(nameVersion);
@ -92,7 +92,7 @@ void createGraphicPackDownloadedVersionFile(const char* nameVersion)
void deleteDownloadedGraphicPacks() void deleteDownloadedGraphicPacks()
{ {
const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks"); const auto path = ActiveSettings::GetDataPath("graphicPacks/downloadedGraphicPacks");
std::error_code er; std::error_code er;
if (!fs::exists(path)) if (!fs::exists(path))
return; return;
@ -240,7 +240,7 @@ void DownloadGraphicPacksWindow::UpdateThread()
return; return;
} }
auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks"); auto path = ActiveSettings::GetDataPath("graphicPacks/downloadedGraphicPacks");
std::error_code er; std::error_code er;
//fs::remove_all(path, er); -> Don't delete the whole folder and recreate it immediately afterwards because sometimes it just fails //fs::remove_all(path, er); -> Don't delete the whole folder and recreate it immediately afterwards because sometimes it just fails
deleteDownloadedGraphicPacks(); deleteDownloadedGraphicPacks();
@ -260,7 +260,7 @@ void DownloadGraphicPacksWindow::UpdateThread()
std::strstr(sb.name, "..\\") != nullptr) std::strstr(sb.name, "..\\") != nullptr)
continue; // bad path continue; // bad path
path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/{}", sb.name); path = ActiveSettings::GetDataPath("graphicPacks/downloadedGraphicPacks/{}", sb.name);
size_t sbNameLen = strlen(sb.name); size_t sbNameLen = strlen(sb.name);
if(sbNameLen == 0) if(sbNameLen == 0)

View file

@ -1002,7 +1002,7 @@ void MainWindow::OnDebugSetting(wxCommandEvent& event)
{ {
try try
{ {
const auto path = CemuApp::GetCemuPath(L"dump\\curl").ToStdWstring(); const auto path = ActiveSettings::GetDataPath(L"dump/curl").generic_wstring();
fs::create_directories(path); fs::create_directories(path);
} }
catch (const std::exception& ex) catch (const std::exception& ex)
@ -1059,8 +1059,8 @@ void MainWindow::OnDebugDumpUsedTextures(wxCommandEvent& event)
try try
{ {
// create directory // create directory
const auto path = CemuApp::GetCemuPath(L"dump\\textures"); const auto path = ActiveSettings::GetDataPath(L"dump/textures");
fs::create_directories(path.ToStdWstring()); fs::create_directories(path.generic_wstring());
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
@ -1080,8 +1080,8 @@ void MainWindow::OnDebugDumpUsedShaders(wxCommandEvent& event)
try try
{ {
// create directory // create directory
const auto path = CemuApp::GetCemuPath(L"dump\\shaders"); const auto path = ActiveSettings::GetDataPath(L"dump/shaders");
fs::create_directories(path.ToStdWstring()); fs::create_directories(path.generic_wstring());
} }
catch (const std::exception & ex) catch (const std::exception & ex)
{ {

View file

@ -270,7 +270,7 @@ void MemorySearcherTool::OnFilter(wxCommandEvent& event)
void MemorySearcherTool::Load() void MemorySearcherTool::Load()
{ {
const auto memorySearcherPath = ActiveSettings::GetPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); const auto memorySearcherPath = ActiveSettings::GetConfigPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId());
auto memSearcherIniContents = FileStream::LoadIntoMemory(memorySearcherPath); auto memSearcherIniContents = FileStream::LoadIntoMemory(memorySearcherPath);
if (!memSearcherIniContents) if (!memSearcherIniContents)
return; return;
@ -322,7 +322,7 @@ void MemorySearcherTool::Load()
void MemorySearcherTool::Save() void MemorySearcherTool::Save()
{ {
const auto memorySearcherPath = ActiveSettings::GetPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); const auto memorySearcherPath = ActiveSettings::GetConfigPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId());
FileStream* fs = FileStream::createFile2(memorySearcherPath); FileStream* fs = FileStream::createFile2(memorySearcherPath);
if (fs) if (fs)
{ {

View file

@ -272,7 +272,7 @@ DebuggerWindow2::DebuggerWindow2(wxFrame& parent, const wxRect& display_size)
{ {
this->wxWindowBase::SetBackgroundColour(*wxWHITE); this->wxWindowBase::SetBackgroundColour(*wxWHITE);
const auto file = ActiveSettings::GetPath("debugger/config.xml"); const auto file = ActiveSettings::GetConfigPath("debugger/config.xml");
m_config.SetFilename(file.generic_wstring()); m_config.SetFilename(file.generic_wstring());
m_config.Load(); m_config.Load();
@ -472,7 +472,7 @@ bool DebuggerWindow2::Show(bool show)
std::wstring DebuggerWindow2::GetModuleStoragePath(std::string module_name, uint32_t crc_hash) const std::wstring DebuggerWindow2::GetModuleStoragePath(std::string module_name, uint32_t crc_hash) const
{ {
if (module_name.empty() || crc_hash == 0) return std::wstring(); if (module_name.empty() || crc_hash == 0) return std::wstring();
return ActiveSettings::GetPath("debugger/{}_{:#10x}.xml", module_name, crc_hash).generic_wstring(); return ActiveSettings::GetConfigPath("debugger/{}_{:#10x}.xml", module_name, crc_hash).generic_wstring();
} }
void DebuggerWindow2::OnBreakpointHit(wxCommandEvent& event) void DebuggerWindow2::OnBreakpointHit(wxCommandEvent& event)

View file

@ -672,10 +672,10 @@ void InputSettings2::on_profile_delete(wxCommandEvent& event)
} }
try try
{ {
const fs::path old_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}.txt", selection)); const fs::path old_path = ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/{}.txt", selection));
fs::remove(old_path); fs::remove(old_path);
const fs::path path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}.xml", selection)); const fs::path path = ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/{}.xml", selection));
fs::remove(path); fs::remove(path);
profile_names->ChangeValue(_(kDefaultProfileName)); profile_names->ChangeValue(_(kDefaultProfileName));

View file

@ -76,9 +76,9 @@ bool InputManager::load(size_t player_index, std::string_view filename)
{ {
fs::path file_path; fs::path file_path;
if (filename.empty()) if (filename.empty())
file_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}", player_index)); file_path = ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/controller{}", player_index));
else else
file_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}", filename)); file_path = ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/{}", filename));
auto old_file = file_path; auto old_file = file_path;
old_file.replace_extension(".txt"); // test .txt extension old_file.replace_extension(".txt"); // test .txt extension
@ -448,7 +448,7 @@ bool InputManager::save(size_t player_index, std::string_view filename)
if (!emulated_controller) if (!emulated_controller)
return false; return false;
fs::path file_path = ActiveSettings::GetPath("controllerProfiles"); fs::path file_path = ActiveSettings::GetConfigPath("controllerProfiles");
fs::create_directories(file_path); fs::create_directories(file_path);
const auto is_default_file = filename.empty(); const auto is_default_file = filename.empty();
@ -664,8 +664,8 @@ EmulatedControllerPtr InputManager::delete_controller(size_t player_index, bool
if(delete_profile) if(delete_profile)
{ {
std::error_code ec{}; std::error_code ec{};
fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec); fs::remove(ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec);
fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec); fs::remove(ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec);
} }
return result; return result;
@ -680,8 +680,8 @@ EmulatedControllerPtr InputManager::delete_controller(size_t player_index, bool
controller = {}; controller = {};
std::error_code ec{}; std::error_code ec{};
fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec); fs::remove(ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec);
fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec); fs::remove(ActiveSettings::GetConfigPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec);
return result; return result;
} }
@ -782,7 +782,7 @@ void InputManager::apply_game_profile()
std::vector<std::string> InputManager::get_profiles() std::vector<std::string> InputManager::get_profiles()
{ {
const auto path = ActiveSettings::GetPath("controllerProfiles"); const auto path = ActiveSettings::GetConfigPath("controllerProfiles");
if (!exists(path)) if (!exists(path))
return {}; return {};

View file

@ -160,7 +160,7 @@ void _putenvSafe(const char* c)
void reconfigureGLDrivers() void reconfigureGLDrivers()
{ {
// reconfigure GL drivers to store // reconfigure GL drivers to store
const fs::path nvCacheDir = ActiveSettings::GetPath("shaderCache/driver/nvidia/"); const fs::path nvCacheDir = ActiveSettings::GetCachePath("shaderCache/driver/nvidia/");
std::error_code err; std::error_code err;
fs::create_directories(nvCacheDir, err); fs::create_directories(nvCacheDir, err);
@ -242,7 +242,7 @@ void unitTests()
int mainEmulatorHLE() int mainEmulatorHLE()
{ {
if (!TestWriteAccess(ActiveSettings::GetPath())) if (!TestWriteAccess(ActiveSettings::GetConfigPath()))
wxMessageBox("Cemu doesn't have write access to it's own directory.\nPlease move it to a different location or run Cemu as administrator!", "Warning", wxOK|wxICON_ERROR); // todo - different error messages per OS wxMessageBox("Cemu doesn't have write access to it's own directory.\nPlease move it to a different location or run Cemu as administrator!", "Warning", wxOK|wxICON_ERROR); // todo - different error messages per OS
LatteOverlay_init(); LatteOverlay_init();
// run a couple of tests if in non-release mode // run a couple of tests if in non-release mode
@ -264,7 +264,7 @@ int mainEmulatorHLE()
// init Cafe system (todo - the stuff above should be part of this too) // init Cafe system (todo - the stuff above should be part of this too)
CafeSystem::Initialize(); CafeSystem::Initialize();
// init title list // init title list
CafeTitleList::Initialize(ActiveSettings::GetPath("title_list_cache.xml")); CafeTitleList::Initialize(ActiveSettings::GetCachePath("title_list_cache.xml"));
for (auto& it : GetConfig().game_paths) for (auto& it : GetConfig().game_paths)
CafeTitleList::AddScanPath(it); CafeTitleList::AddScanPath(it);
fs::path mlcPath = ActiveSettings::GetMlcPath(); fs::path mlcPath = ActiveSettings::GetMlcPath();

View file

@ -18,7 +18,7 @@ void libusbWrapper::init()
m_module = LoadLibraryW(L"libusb-1.0.dll"); m_module = LoadLibraryW(L"libusb-1.0.dll");
if (!m_module) if (!m_module)
{ {
const auto path = ActiveSettings::GetPath("resources/libusb-1.0.dll"); const auto path = ActiveSettings::GetSystemDataPath("resources/libusb-1.0.dll");
m_module = LoadLibraryW(path.generic_wstring().c_str()); m_module = LoadLibraryW(path.generic_wstring().c_str());
if (!m_module) if (!m_module)
{ {