diff --git a/CMakeLists.txt b/CMakeLists.txt index 76dcd33a..b973a3f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.21.1) option(ENABLE_VCPKG "Enable the vcpkg package manager" ON) +option(PORTABLE "All data created and maintained by Cemu will be in the directory where the executable file is located" ON) set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version if (EXPERIMENTAL_VERSION) @@ -30,6 +31,10 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) add_compile_definitions($<$:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT +if(PORTABLE) + add_compile_definitions(PORTABLE) +endif() + set_property(GLOBAL PROPERTY USE_FOLDERS ON) # enable link time optimization for release builds diff --git a/src/Cafe/Account/Account.cpp b/src/Cafe/Account/Account.cpp index 2cf424f1..f1ce0be8 100644 --- a/src/Cafe/Account/Account.cpp +++ b/src/Cafe/Account/Account.cpp @@ -424,7 +424,7 @@ OnlineValidator Account::ValidateOnlineFiles() const { OnlineValidator result{}; - const auto otp = ActiveSettings::GetPath("otp.bin"); + const auto otp = ActiveSettings::GetUserDataPath("otp.bin"); if (!fs::exists(otp)) result.otp = OnlineValidator::FileState::Missing; else if (fs::file_size(otp) != 1024) @@ -432,7 +432,7 @@ OnlineValidator Account::ValidateOnlineFiles() const else result.otp = OnlineValidator::FileState::Ok; - const auto seeprom = ActiveSettings::GetPath("seeprom.bin"); + const auto seeprom = ActiveSettings::GetUserDataPath("seeprom.bin"); if (!fs::exists(seeprom)) result.seeprom = OnlineValidator::FileState::Missing; else if (fs::file_size(seeprom) != 512) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 2cadc106..e2e1c5ef 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -289,7 +289,7 @@ uint32 loadSharedData() for (sint32 i = 0; i < sizeof(shareddataDef) / sizeof(shareddataDef[0]); i++) { bool existsInMLC = fs::exists(ActiveSettings::GetMlcPath(shareddataDef[i].mlcPath)); - bool existsInResources = fs::exists(ActiveSettings::GetPath(shareddataDef[i].resourcePath)); + bool existsInResources = fs::exists(ActiveSettings::GetDataPath(shareddataDef[i].resourcePath)); if (!existsInMLC && !existsInResources) { @@ -314,7 +314,7 @@ uint32 loadSharedData() // alternatively fall back to our shared fonts if (!fontFile) { - path = ActiveSettings::GetPath(shareddataDef[i].resourcePath); + path = ActiveSettings::GetDataPath(shareddataDef[i].resourcePath); fontFile = FileStream::openFile2(path); } if (!fontFile) @@ -340,7 +340,7 @@ uint32 loadSharedData() return memory_getVirtualOffsetFromPointer(dataWritePtr); } // alternative method: load RAM dump - const auto path = ActiveSettings::GetPath("shareddata.bin"); + const auto path = ActiveSettings::GetUserDataPath("shareddata.bin"); FileStream* ramDumpFile = FileStream::openFile2(path); if (ramDumpFile) { diff --git a/src/Cafe/Filesystem/FST/KeyCache.cpp b/src/Cafe/Filesystem/FST/KeyCache.cpp index 587a5dd6..5d8d51c1 100644 --- a/src/Cafe/Filesystem/FST/KeyCache.cpp +++ b/src/Cafe/Filesystem/FST/KeyCache.cpp @@ -59,7 +59,7 @@ void KeyCache_Prepare() sKeyCachePrepared = true; g_keyCache.clear(); // load keys - auto keysPath = ActiveSettings::GetPath("keys.txt"); + auto keysPath = ActiveSettings::GetUserDataPath("keys.txt"); FileStream* fs_keys = FileStream::openFile2(keysPath); if( !fs_keys ) { diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp index 9f2550c2..d8c735ce 100644 --- a/src/Cafe/GameProfile/GameProfile.cpp +++ b/src/Cafe/GameProfile/GameProfile.cpp @@ -180,12 +180,12 @@ void gameProfile_load() bool GameProfile::Load(uint64_t title_id) { - auto gameProfilePath = ActiveSettings::GetPath("gameProfiles/{:016x}.ini", title_id); + auto gameProfilePath = ActiveSettings::GetConfigPath("gameProfiles/{:016x}.ini", title_id); std::optional> profileContents = FileStream::LoadIntoMemory(gameProfilePath); if (!profileContents) { - gameProfilePath = ActiveSettings::GetPath("gameProfiles/default/{:016x}.ini", title_id); + gameProfilePath = ActiveSettings::GetDataPath("gameProfiles/default/{:016x}.ini", title_id); profileContents = FileStream::LoadIntoMemory(gameProfilePath); if (!profileContents) return false; @@ -276,7 +276,12 @@ bool GameProfile::Load(uint64_t title_id) void GameProfile::Save(uint64_t title_id) { - auto gameProfilePath = ActiveSettings::GetPath("gameProfiles/{:016x}.ini", title_id); + auto gameProfileDir = ActiveSettings::GetConfigPath("gameProfiles"); + if (std::error_code ex_ec; !fs::exists(gameProfileDir, ex_ec) && !ex_ec) { + std::error_code cr_ec; + fs::create_directories(gameProfileDir, cr_ec); + } + auto gameProfilePath = gameProfileDir / fmt::format("{:016x}.ini", title_id); FileStream* fs = FileStream::createFile2(gameProfilePath); if (!fs) { diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp index 959441d7..a81ec03c 100644 --- a/src/Cafe/GraphicPack/GraphicPack2.cpp +++ b/src/Cafe/GraphicPack/GraphicPack2.cpp @@ -63,7 +63,7 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath) void GraphicPack2::LoadAll() { std::error_code ec; - fs::path basePath = ActiveSettings::GetPath("graphicPacks"); + fs::path basePath = ActiveSettings::GetUserDataPath("graphicPacks"); for (fs::recursive_directory_iterator it(basePath, ec); it != end(it); ++it) { if (!it->is_directory(ec)) @@ -93,7 +93,7 @@ bool GraphicPack2::LoadGraphicPack(const std::wstring& filename, IniParser& rule if (it == config_entries.cend()) { // check for relative path - it = config_entries.find(MakeRelativePath(gp->GetFilename2()).lexically_normal()); + it = config_entries.find(MakeRelativePath(ActiveSettings::GetUserDataPath(), gp->GetFilename2()).lexically_normal()); } if (it != config_entries.cend()) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index e39d0e86..ba85898c 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -197,17 +197,17 @@ void LatteShaderCache_load() LatteShaderCache_initCompileQueue(); // create directories std::error_code ec; - fs::create_directories(ActiveSettings::GetPath("shaderCache/transferable"), ec); - fs::create_directories(ActiveSettings::GetPath("shaderCache/precompiled"), ec); + fs::create_directories(ActiveSettings::GetCachePath("shaderCache/transferable"), ec); + fs::create_directories(ActiveSettings::GetCachePath("shaderCache/precompiled"), ec); // initialize renderer specific caches if (g_renderer->GetType() == RendererAPI::Vulkan) RendererShaderVk::ShaderCacheLoading_begin(cacheTitleId); else if (g_renderer->GetType() == RendererAPI::OpenGL) RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId); // get cache file name - const auto pathGeneric = ActiveSettings::GetPath("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_16_0 = ActiveSettings::GetPath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0 + const auto pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId); + const auto pathGenericPre1_25_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.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); // calculate extraVersion for transferable and precompiled shader cache diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index e9e86f53..dc088ae3 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -279,7 +279,7 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId) { const uint32 cacheMagic = GeneratePrecompiledCacheId(); 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); if (g_programBinaryCache == nullptr) cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename); diff --git a/src/Cafe/HW/Latte/Renderer/Renderer.cpp b/src/Cafe/HW/Latte/Renderer/Renderer.cpp index c7f7b814..8f99c069 100644 --- a/src/Cafe/HW/Latte/Renderer/Renderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Renderer.cpp @@ -133,7 +133,7 @@ void Renderer::SaveScreenshot(const std::vector& rgb_data, int width, int // save to png file if (save_screenshot) { - fs::path screendir = ActiveSettings::GetPath("screenshots"); + fs::path screendir = ActiveSettings::GetUserDataPath("screenshots"); if (!fs::exists(screendir)) fs::create_directory(screendir); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index e6677576..7c577903 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -442,7 +442,7 @@ void RendererShaderVk::ShaderCacheLoading_begin(uint64 cacheTitleId) } uint32 spirvCacheMagic = GeneratePrecompiledCacheId(); 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); if (s_spirvCache == nullptr) cemuLog_log(LogType::Force, "Unable to open SPIR-V cache {}", cacheFilename); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp index bb6c966e..38f7c882 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp @@ -32,8 +32,8 @@ VulkanPipelineStableCache& VulkanPipelineStableCache::GetInstance() uint32 VulkanPipelineStableCache::BeginLoading(uint64 cacheTitleId) { std::error_code ec; - fs::create_directories(ActiveSettings::GetPath("shaderCache/transferable"), ec); - const auto pathCacheFile = ActiveSettings::GetPath("shaderCache/transferable/{:016x}_vkpipeline.bin", cacheTitleId); + fs::create_directories(ActiveSettings::GetCachePath("shaderCache/transferable"), ec); + const auto pathCacheFile = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_vkpipeline.bin", cacheTitleId); // init cache loader state g_vkCacheState.pipelineLoadIndex = 0; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 249d06b7..5cbf7f94 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -2326,7 +2326,7 @@ void VulkanRenderer::WaitCommandBufferFinished(uint64 commandBufferId) 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)) { try @@ -2403,7 +2403,7 @@ void VulkanRenderer::PipelineCacheSaveThread(size_t cache_size) void VulkanRenderer::CreatePipelineCache() { std::vector cacheData; - const auto dir = ActiveSettings::GetPath("shaderCache/driver/vk"); + const auto dir = ActiveSettings::GetCachePath("shaderCache/driver/vk"); if (fs::exists(dir)) { const auto filename = dir / fmt::format("{:016x}.bin", CafeSystem::GetForegroundTitleId()); diff --git a/src/Cafe/HW/MMU/MMU.cpp b/src/Cafe/HW/MMU/MMU.cpp index 87bf5722..9e22d907 100644 --- a/src/Cafe/HW/MMU/MMU.cpp +++ b/src/Cafe/HW/MMU/MMU.cpp @@ -409,7 +409,7 @@ void memory_writeDumpFile(uint32 startAddr, uint32 size, const fs::path& path) void memory_createDump() { const uint32 pageSize = MemMapper::GetPageSize(); - fs::path path = ActiveSettings::GetPath("dump/ramDump{:}", (uint32)time(nullptr)); + fs::path path = ActiveSettings::GetUserDataPath("dump/ramDump{:}", (uint32)time(nullptr)); fs::create_directories(path); for (auto& itr : g_mmuRanges) diff --git a/src/Cafe/IOSU/legacy/iosu_crypto.cpp b/src/Cafe/IOSU/legacy/iosu_crypto.cpp index e74a93e2..961ab70d 100644 --- a/src/Cafe/IOSU/legacy/iosu_crypto.cpp +++ b/src/Cafe/IOSU/legacy/iosu_crypto.cpp @@ -563,7 +563,7 @@ void iosuCrypto_loadSSLCertificates() void iosuCrypto_init() { // 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::GetUserDataPath("otp.bin"), std::ifstream::in | std::ios::binary); otp_file.is_open()) { otp_file.seekg(0, std::ifstream::end); const auto length = otp_file.tellg(); @@ -586,7 +586,7 @@ void iosuCrypto_init() 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::GetUserDataPath("seeprom.bin"), std::ifstream::in | std::ios::binary); seeprom_file.is_open()) { seeprom_file.seekg(0, std::ifstream::end); const auto length = seeprom_file.tellg(); @@ -630,13 +630,13 @@ sint32 iosuCrypt_checkRequirementsForOnlineMode(std::wstring& additionalErrorInf { std::error_code ec; // check if otp.bin is present - const auto otp_file = ActiveSettings::GetPath("otp.bin"); + const auto otp_file = ActiveSettings::GetUserDataPath("otp.bin"); if(!fs::exists(otp_file, ec)) return IOS_CRYPTO_ONLINE_REQ_OTP_MISSING; if(fs::file_size(otp_file, ec) != 1024) return IOS_CRYPTO_ONLINE_REQ_OTP_CORRUPTED; // check if seeprom.bin is present - const auto seeprom_file = ActiveSettings::GetPath("seeprom.bin"); + const auto seeprom_file = ActiveSettings::GetUserDataPath("seeprom.bin"); if (!fs::exists(seeprom_file, ec)) return IOS_CRYPTO_ONLINE_REQ_SEEPROM_MISSING; if (fs::file_size(seeprom_file, ec) != 512) diff --git a/src/Cafe/OS/RPL/rpl.cpp b/src/Cafe/OS/RPL/rpl.cpp index 66d7a4ca..43e39d5b 100644 --- a/src/Cafe/OS/RPL/rpl.cpp +++ b/src/Cafe/OS/RPL/rpl.cpp @@ -2116,7 +2116,7 @@ void RPLLoader_LoadDependency(rplDependency_t* dependency) // attempt to load rpl from Cemu's /cafeLibs/ directory if (ActiveSettings::LoadSharedLibrariesEnabled()) { - const auto filePath = ActiveSettings::GetPath("cafeLibs/{}", dependency->filepath); + const auto filePath = ActiveSettings::GetUserDataPath("cafeLibs/{}", dependency->filepath); auto fileData = FileStream::LoadIntoMemory(filePath); if (fileData) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index c49607e1..1853bae8 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -107,7 +107,7 @@ namespace coreinit return; std::error_code ec; - const auto path = ActiveSettings::GetPath("sdcard/"); + const auto path = ActiveSettings::GetUserDataPath("sdcard/"); fs::create_directories(path, ec); FSCDeviceHostFS_Mount("/vol/external01", _pathToUtf8(path), FSC_PRIORITY_BASE); @@ -140,7 +140,7 @@ namespace coreinit return FS_RESULT::ERR_PLACEHOLDER; std::error_code ec; - const auto path = ActiveSettings::GetPath("sdcard/"); + const auto path = ActiveSettings::GetUserDataPath("sdcard/"); fs::create_directories(path, ec); if (!FSCDeviceHostFS_Mount(mountPathOut, _pathToUtf8(path), FSC_PRIORITY_BASE)) return FS_RESULT::ERR_PLACEHOLDER; diff --git a/src/Cafe/TitleList/TitleInfo.cpp b/src/Cafe/TitleList/TitleInfo.cpp index ef97e6eb..10710c43 100644 --- a/src/Cafe/TitleList/TitleInfo.cpp +++ b/src/Cafe/TitleList/TitleInfo.cpp @@ -291,7 +291,7 @@ void TitleInfo::CalcUID() fs::path normalizedPath; if (m_fullPath.is_relative()) { - normalizedPath = ActiveSettings::GetPath(); + normalizedPath = ActiveSettings::GetUserDataPath(); normalizedPath /= m_fullPath; } else diff --git a/src/Cemu/Logging/CemuLogging.cpp b/src/Cemu/Logging/CemuLogging.cpp index 7e6669a8..28a86427 100644 --- a/src/Cemu/Logging/CemuLogging.cpp +++ b/src/Cemu/Logging/CemuLogging.cpp @@ -98,7 +98,7 @@ void cemuLog_createLogFile(bool triggeredByCrash) if (LogContext.file_stream.is_open()) return; - const auto path = ActiveSettings::GetPath("log.txt"); + const auto path = ActiveSettings::GetUserDataPath("log.txt"); LogContext.file_stream.open(path, std::ios::out); if (LogContext.file_stream.fail()) { diff --git a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp index 25dca26f..565f4f8f 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp @@ -61,7 +61,7 @@ bool CreateMiniDump(CrashDump dump, EXCEPTION_POINTERS* pep) if (dump == CrashDump::Disabled) return true; - fs::path p = ActiveSettings::GetPath("crashdump"); + fs::path p = ActiveSettings::GetUserDataPath("crashdump"); std::error_code ec; fs::create_directories(p, ec); @@ -356,11 +356,11 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context) const auto temp_time = std::chrono::system_clock::to_time_t(now); const auto& time = *std::gmtime(&temp_time); - fs::path p = ActiveSettings::GetPath("crashdump"); + fs::path p = ActiveSettings::GetUserDataPath("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); std::error_code ec; - fs::copy_file(ActiveSettings::GetPath("log.txt"), p, ec); + fs::copy_file(ActiveSettings::GetUserDataPath("log.txt"), p, ec); } exit(0); diff --git a/src/config/ActiveSettings.cpp b/src/config/ActiveSettings.cpp index 16119725..bef9cf0b 100644 --- a/src/config/ActiveSettings.cpp +++ b/src/config/ActiveSettings.cpp @@ -1,6 +1,7 @@ #include "config/ActiveSettings.h" #include "Cafe/GameProfile/GameProfile.h" +#include "Cemu/Logging/CemuLogging.h" #include "LaunchSettings.h" #include "util/helpers/helpers.h" @@ -12,17 +13,41 @@ extern bool alwaysDisplayDRC; -void ActiveSettings::LoadOnce() +std::set +ActiveSettings::LoadOnce(const fs::path& user_data_path, + const fs::path& config_path, + const fs::path& cache_path, + const fs::path& data_path) { s_full_path = boost::dll::program_location().generic_wstring(); - s_path = s_full_path.parent_path(); + + s_user_data_path = user_data_path; + s_config_path = config_path; + s_cache_path = cache_path; + s_data_path = data_path; + std::set failed_write_access; + for (auto&& path : {user_data_path, config_path, cache_path}) + { + if (!fs::exists(path)) + { + std::error_code ec; + fs::create_directories(path, ec); + } + if (!TestWriteAccess(path)) + { + cemuLog_log(LogType::Force, "Failed to write to {}", path.generic_string()); + failed_write_access.insert(path); + } + } + 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(); LaunchSettings::ChangeNetworkServiceURL(GetConfig().account.active_service); std::wstring additionalErrorInfo; s_has_required_online_files = iosuCrypt_checkRequirementsForOnlineMode(additionalErrorInfo) == IOS_CRYPTO_ONLINE_REQ_OK; + return failed_write_access; } bool ActiveSettings::LoadSharedLibrariesEnabled() @@ -226,6 +251,6 @@ fs::path ActiveSettings::GetMlcPath() fs::path ActiveSettings::GetDefaultMLCPath() { - return GetPath("mlc01"); + return GetUserDataPath("mlc01"); } diff --git a/src/config/ActiveSettings.h b/src/config/ActiveSettings.h index ae3feb94..9621b4d0 100644 --- a/src/config/ActiveSettings.h +++ b/src/config/ActiveSettings.h @@ -1,69 +1,70 @@ #pragma once +#include #include "config/CemuConfig.h" #include "config/NetworkSettings.h" // global active settings for fast access (reflects settings from command line and game profile) class ActiveSettings { -public: - static void LoadOnce(); - - [[nodiscard]] static fs::path GetFullPath() { return s_full_path; } - [[nodiscard]] static fs::path GetPath() { return s_path; } - [[nodiscard]] static fs::path GetFilename() { return s_filename; } - - [[nodiscard]] static fs::path GetMlcPath(); - - [[nodiscard]] static fs::path GetPath(std::string_view p) - { - std::basic_string_view s((const char8_t*)p.data(), p.size()); - return s_path / fs::path(s); - } - - [[nodiscard]] static fs::path GetMlcPath(std::string_view p) - { - std::basic_string_view s((const char8_t*)p.data(), p.size()); - return GetMlcPath() / fs::path(s); - } - +private: template - [[nodiscard]] static fs::path GetPath(std::string_view format, TArgs&&... args) + static fs::path GetPath(const fs::path& path, std::string_view format, TArgs&&... args) { cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\')); std::string tmpPathStr = fmt::format(fmt::runtime(format), std::forward(args)...); - std::basic_string_view s((const char8_t*)tmpPathStr.data(), tmpPathStr.size()); - return s_path / fs::path(s); + return path / _utf8ToPath(tmpPathStr); } - + template - [[nodiscard]] static fs::path GetPath(std::wstring_view format, TArgs&&... args) + static fs::path GetPath(const fs::path& path, std::wstring_view format, TArgs&&... args) { cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\')); - return s_path / fmt::format(format, std::forward(args)...); + return path / fmt::format(fmt::runtime(format), std::forward(args)...); } - - template - [[nodiscard]] static fs::path GetMlcPath(std::string_view format, TArgs&&... args) + static fs::path GetPath(const fs::path& path, std::string_view p) { - cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\')); - auto tmp = fmt::format(fmt::runtime(format), std::forward(args)...); - return GetMlcPath() / _utf8ToPath(tmp); + std::basic_string_view s((const char8_t*)p.data(), p.size()); + return path / fs::path(s); } - - template - [[nodiscard]] static fs::path GetMlcPath(std::wstring_view format, TArgs&&... args) + static fs::path GetPath(const fs::path& path) { - cemu_assert_debug(format.empty() || (format[0] != L'/' && format[0] != L'\\')); - return GetMlcPath() / fmt::format(fmt::runtime(format), std::forward(args)...); + return path; } - + +public: + // Set directories and return all directories that failed write access test + static std::set + LoadOnce(const fs::path& user_data_path, + const fs::path& config_path, + const fs::path& cache_path, + const fs::path& data_path); + + [[nodiscard]] static fs::path GetFullPath() { return s_full_path; } + [[nodiscard]] static fs::path GetFilename() { return s_filename; } + template + [[nodiscard]] static fs::path GetUserDataPath(TArgs&&... args){ return GetPath(s_user_data_path, std::forward(args)...); }; + template + [[nodiscard]] static fs::path GetConfigPath(TArgs&&... args){ return GetPath(s_config_path, std::forward(args)...); }; + template + [[nodiscard]] static fs::path GetCachePath(TArgs&&... args){ return GetPath(s_cache_path, std::forward(args)...); }; + template + [[nodiscard]] static fs::path GetDataPath(TArgs&&... args){ return GetPath(s_data_path, std::forward(args)...); }; + + [[nodiscard]] static fs::path GetMlcPath(); + + template + [[nodiscard]] static fs::path GetMlcPath(TArgs&&... args){ return GetPath(GetMlcPath(), std::forward(args)...); }; + // get mlc path to default cemu root dir/mlc01 [[nodiscard]] static fs::path GetDefaultMLCPath(); private: inline static fs::path s_full_path; // full filename - inline static fs::path s_path; // path + inline static fs::path s_user_data_path; + inline static fs::path s_config_path; + inline static fs::path s_cache_path; + inline static fs::path s_data_path; inline static fs::path s_filename; // cemu.exe inline static fs::path s_mlc_path; diff --git a/src/config/NetworkSettings.cpp b/src/config/NetworkSettings.cpp index 210263ef..2227b981 100644 --- a/src/config/NetworkSettings.cpp +++ b/src/config/NetworkSettings.cpp @@ -1,4 +1,5 @@ #include "NetworkSettings.h" +#include "ActiveSettings.h" #include "LaunchSettings.h" #include "CemuConfig.h" #include @@ -6,11 +7,10 @@ XMLNetworkConfig_t n_config(L"network_services.xml"); + void NetworkConfig::LoadOnce() { - s_full_path = boost::dll::program_location().generic_wstring(); - s_path = s_full_path.parent_path(); - n_config.SetFilename(GetPath("network_services.xml").generic_wstring()); + n_config.SetFilename(ActiveSettings::GetConfigPath("network_services.xml").generic_wstring()); if (XMLExists()) n_config.Load(); } @@ -37,7 +37,7 @@ void NetworkConfig::Load(XMLConfigParser& parser) bool NetworkConfig::XMLExists() { std::error_code ec; - if (!fs::exists(GetPath("network_services.xml"), ec)) + if (!fs::exists(ActiveSettings::GetConfigPath("network_services.xml"), ec)) { if (static_cast(GetConfig().account.active_service.GetValue()) == NetworkService::Custom) { diff --git a/src/config/NetworkSettings.h b/src/config/NetworkSettings.h index e65da8ab..f289e679 100644 --- a/src/config/NetworkSettings.h +++ b/src/config/NetworkSettings.h @@ -38,14 +38,6 @@ struct NetworkConfig { void Save(XMLConfigParser& parser); static bool XMLExists(); - private: - inline static fs::path s_path; - inline static fs::path s_full_path; - [[nodiscard]] static fs::path GetPath(std::string_view p) - { - std::basic_string_view s((const char8_t*)p.data(), p.size()); - return s_path / fs::path(s); - } }; struct NintendoURLs { diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index de60f8bc..50e9e04c 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "Cafe/TitleList/TitleList.h" #include "Cafe/TitleList/SaveList.h" @@ -24,6 +25,8 @@ wxIMPLEMENT_APP_NO_MAIN(CemuApp); extern WindowInfo g_window_info; extern std::shared_mutex g_mutex; +int mainEmulatorHLE(); +void HandlePostUpdate(); // Translation strings to extract for gettext: void unused_translation_dummy() { @@ -70,6 +73,42 @@ void unused_translation_dummy() bool CemuApp::OnInit() { + fs::path user_data_path, config_path, cache_path, data_path; + auto standardPaths = wxStandardPaths::Get(); +#ifdef PORTABLE + fs::path exePath(standardPaths.GetExecutablePath().ToStdString()); + user_data_path = config_path = cache_path = data_path = exePath.parent_path(); +#else + SetAppName("Cemu"); + wxString appName=GetAppName(); + #ifdef BOOST_OS_LINUX + standardPaths.SetFileLayout(wxStandardPaths::FileLayout::FileLayout_XDG); + auto getEnvDir = [&](const wxString& varName, const wxString& defaultValue) + { + wxString dir; + if (!wxGetEnv(varName, &dir) || dir.empty()) + return defaultValue; + return dir; + }; + wxString homeDir=wxFileName::GetHomeDir(); + user_data_path = (getEnvDir(wxS("XDG_DATA_HOME"), homeDir + wxS("/.local/share")) + "/" + appName).ToStdString(); + config_path = (getEnvDir(wxS("XDG_CONFIG_HOME"), homeDir + wxS("/.config")) + "/" + appName).ToStdString(); + #else + user_data_path = config_path = standardPaths.GetUserDataDir().ToStdString(); + #endif + data_path = standardPaths.GetDataDir().ToStdString(); + cache_path = standardPaths.GetUserDir(wxStandardPaths::Dir::Dir_Cache).ToStdString(); + cache_path /= appName.ToStdString(); +#endif + auto failed_write_access = ActiveSettings::LoadOnce(user_data_path, config_path, cache_path, data_path); + for (auto&& path : failed_write_access) + wxMessageBox(fmt::format("Cemu can't write to {} !", path.generic_string()), _("Warning"), wxOK | wxCENTRE | wxICON_EXCLAMATION, nullptr); + + NetworkConfig::LoadOnce(); + + HandlePostUpdate(); + mainEmulatorHLE(); + wxInitAllImageHandlers(); g_config.Load(); @@ -83,7 +122,7 @@ bool CemuApp::OnInit() { if (m_locale.Init(language)) { - m_locale.AddCatalogLookupPathPrefix("./resources"); + m_locale.AddCatalogLookupPathPrefix(ActiveSettings::GetDataPath("resources").generic_string()); m_locale.AddCatalog("cemu"); } } @@ -115,9 +154,6 @@ bool CemuApp::OnInit() Bind(wxEVT_ACTIVATE_APP, &CemuApp::ActivateApp, this); - if (!TestWriteAccess(ActiveSettings::GetPath())) - 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(); const bool first_start = !config.did_show_graphic_pack_download; @@ -187,7 +223,7 @@ int CemuApp::FilterEvent(wxEvent& event) std::vector CemuApp::GetAvailableLanguages() { - const auto path = ActiveSettings::GetPath("resources"); + const auto path = ActiveSettings::GetDataPath("resources"); if (!exists(path)) return {}; @@ -312,11 +348,11 @@ void CemuApp::CreateDefaultFiles(bool first_start) // cemu directories try { - const auto controllerProfileFolder = GetCemuPath(L"controllerProfiles").ToStdWstring(); + const auto controllerProfileFolder = GetConfigPath(L"controllerProfiles").ToStdWstring(); if (!fs::exists(controllerProfileFolder)) fs::create_directories(controllerProfileFolder); - const auto memorySearcherFolder = GetCemuPath(L"memorySearcher").ToStdWstring(); + const auto memorySearcherFolder = GetUserDataPath(L"memorySearcher").ToStdWstring(); if (!fs::exists(memorySearcherFolder)) fs::create_directories(memorySearcherFolder); } @@ -377,15 +413,6 @@ bool CemuApp::SelectMLCPath(wxWindow* parent) return false; } -wxString CemuApp::GetCemuPath() -{ - return ActiveSettings::GetPath().generic_wstring(); -} - -wxString CemuApp::GetCemuPath(const wxString& cat) -{ - return ActiveSettings::GetPath(cat.ToStdString()).generic_wstring(); -} wxString CemuApp::GetMLCPath() { @@ -397,6 +424,26 @@ wxString CemuApp::GetMLCPath(const wxString& cat) return ActiveSettings::GetMlcPath(cat.ToStdString()).generic_wstring(); } +wxString CemuApp::GetConfigPath() +{ + return ActiveSettings::GetConfigPath().generic_wstring(); +}; + +wxString CemuApp::GetConfigPath(const wxString& cat) +{ + return ActiveSettings::GetConfigPath(cat.ToStdString()).generic_wstring(); +}; + +wxString CemuApp::GetUserDataPath() +{ + return ActiveSettings::GetUserDataPath().generic_wstring(); +}; + +wxString CemuApp::GetUserDataPath(const wxString& cat) +{ + return ActiveSettings::GetUserDataPath(cat.ToStdString()).generic_wstring(); +}; + void CemuApp::ActivateApp(wxActivateEvent& event) { g_window_info.app_active = event.GetActive(); diff --git a/src/gui/CemuApp.h b/src/gui/CemuApp.h index 888293eb..32504883 100644 --- a/src/gui/CemuApp.h +++ b/src/gui/CemuApp.h @@ -19,8 +19,12 @@ public: static void CreateDefaultFiles(bool first_start = false); static bool SelectMLCPath(wxWindow* parent = nullptr); - static wxString GetCemuPath(); - static wxString GetCemuPath(const wxString& cat); + static wxString GetConfigPath(); + static wxString GetConfigPath(const wxString& cat); + + static wxString GetUserDataPath(); + static wxString GetUserDataPath(const wxString& cat); + static wxString GetMLCPath(); static wxString GetMLCPath(const wxString& cat); private: diff --git a/src/gui/CemuUpdateWindow.cpp b/src/gui/CemuUpdateWindow.cpp index ef537a58..2e2b40eb 100644 --- a/src/gui/CemuUpdateWindow.cpp +++ b/src/gui/CemuUpdateWindow.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -470,7 +471,8 @@ void CemuUpdateWindow::WorkerThread() break; // apply update - std::wstring target_directory = ActiveSettings::GetPath().generic_wstring(); + fs::path exePath = fs::path(wxStandardPaths::Get().GetExecutablePath().ToStdString()); + std::wstring target_directory = exePath.parent_path().generic_wstring(); if (target_directory[target_directory.size() - 1] == '/') target_directory = target_directory.substr(0, target_directory.size() - 1); // remove trailing / diff --git a/src/gui/ChecksumTool.cpp b/src/gui/ChecksumTool.cpp index b8393330..20e9f7ca 100644 --- a/src/gui/ChecksumTool.cpp +++ b/src/gui/ChecksumTool.cpp @@ -134,7 +134,7 @@ ChecksumTool::ChecksumTool(wxWindow* parent, wxTitleManagerList::TitleEntry& ent 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 checksum_path = ActiveSettings::GetPath("resources/checksums/{}", default_file); + const auto checksum_path = ActiveSettings::GetUserDataPath("resources/checksums/{}", default_file); if (exists(checksum_path)) m_verify_online->Enable(); } @@ -186,7 +186,7 @@ void ChecksumTool::LoadOnlineData() const std::string latest_commit; - const auto checksum_path = ActiveSettings::GetPath("resources/checksums"); + const auto checksum_path = ActiveSettings::GetUserDataPath("resources/checksums"); if (exists(checksum_path)) { std::string current_commit; @@ -594,7 +594,7 @@ void ChecksumTool::OnVerifyOnline(wxCommandEvent& event) 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 checksum_path = ActiveSettings::GetPath("resources/checksums/{}", default_file); + const auto checksum_path = ActiveSettings::GetUserDataPath("resources/checksums/{}", default_file); if(!exists(checksum_path)) return; diff --git a/src/gui/DownloadGraphicPacksWindow.cpp b/src/gui/DownloadGraphicPacksWindow.cpp index 973b7c57..4128cc04 100644 --- a/src/gui/DownloadGraphicPacksWindow.cpp +++ b/src/gui/DownloadGraphicPacksWindow.cpp @@ -65,7 +65,7 @@ bool DownloadGraphicPacksWindow::curlDownloadFile(const char *url, curlDownloadF bool checkGraphicPackDownloadedVersion(const char* nameVersion, bool& hasVersionFile) { hasVersionFile = false; - const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/version.txt"); + const auto path = ActiveSettings::GetUserDataPath("graphicPacks/downloadedGraphicPacks/version.txt"); std::unique_ptr file(FileStream::openFile2(path)); std::string versionInFile; @@ -78,7 +78,7 @@ bool checkGraphicPackDownloadedVersion(const char* nameVersion, bool& hasVersion void createGraphicPackDownloadedVersionFile(const char* nameVersion) { - const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/version.txt"); + const auto path = ActiveSettings::GetUserDataPath("graphicPacks/downloadedGraphicPacks/version.txt"); std::unique_ptr file(FileStream::createFile2(path)); if (file) file->writeString(nameVersion); @@ -90,7 +90,7 @@ void createGraphicPackDownloadedVersionFile(const char* nameVersion) void deleteDownloadedGraphicPacks() { - const auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks"); + const auto path = ActiveSettings::GetUserDataPath("graphicPacks/downloadedGraphicPacks"); std::error_code er; if (!fs::exists(path, er)) return; @@ -238,7 +238,7 @@ void DownloadGraphicPacksWindow::UpdateThread() return; } - auto path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks"); + auto path = ActiveSettings::GetUserDataPath("graphicPacks/downloadedGraphicPacks"); 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 deleteDownloadedGraphicPacks(); @@ -258,7 +258,7 @@ void DownloadGraphicPacksWindow::UpdateThread() std::strstr(sb.name, "..\\") != nullptr) continue; // bad path - path = ActiveSettings::GetPath("graphicPacks/downloadedGraphicPacks/{}", sb.name); + path = ActiveSettings::GetUserDataPath("graphicPacks/downloadedGraphicPacks/{}", sb.name); size_t sbNameLen = strlen(sb.name); if(sbNameLen == 0) diff --git a/src/gui/GraphicPacksWindow2.cpp b/src/gui/GraphicPacksWindow2.cpp index bab55156..e718605a 100644 --- a/src/gui/GraphicPacksWindow2.cpp +++ b/src/gui/GraphicPacksWindow2.cpp @@ -3,6 +3,7 @@ #include "gui/DownloadGraphicPacksWindow.h" #include "Cafe/GraphicPack/GraphicPack2.h" #include "config/CemuConfig.h" +#include "config/ActiveSettings.h" #include "Cafe/HW/Latte/Core/LatteAsyncCommands.h" @@ -326,7 +327,7 @@ void GraphicPacksWindow2::SaveStateToConfig() for (const auto& gp : GraphicPack2::GetGraphicPacks()) { - auto filename = MakeRelativePath(gp->GetFilename()).lexically_normal(); + auto filename = MakeRelativePath(ActiveSettings::GetUserDataPath(), gp->GetFilename()).lexically_normal(); if (gp->IsEnabled()) { data.graphic_pack_entries.try_emplace(filename); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index d8caabf4..5ebfe09d 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -989,8 +989,8 @@ void MainWindow::OnDebugSetting(wxCommandEvent& event) { try { - const auto path = CemuApp::GetCemuPath(L"dump\\curl").ToStdWstring(); - fs::create_directories(path); + const fs::path path(CemuApp::GetUserDataPath().ToStdString()); + fs::create_directories(path / "dump" / "curl"); } catch (const std::exception& ex) { @@ -1046,8 +1046,8 @@ void MainWindow::OnDebugDumpUsedTextures(wxCommandEvent& event) try { // create directory - const auto path = CemuApp::GetCemuPath(L"dump\\textures"); - fs::create_directories(path.ToStdWstring()); + const fs::path path(CemuApp::GetUserDataPath().ToStdString()); + fs::create_directories(path / "dump" / "textures"); } catch (const std::exception& ex) { @@ -1067,8 +1067,8 @@ void MainWindow::OnDebugDumpUsedShaders(wxCommandEvent& event) try { // create directory - const auto path = CemuApp::GetCemuPath(L"dump\\shaders"); - fs::create_directories(path.ToStdWstring()); + const fs::path path(CemuApp::GetUserDataPath().ToStdString()); + fs::create_directories(path / "dump" / "shaders"); } catch (const std::exception & ex) { diff --git a/src/gui/MemorySearcherTool.cpp b/src/gui/MemorySearcherTool.cpp index 5caa163f..093f7ffe 100644 --- a/src/gui/MemorySearcherTool.cpp +++ b/src/gui/MemorySearcherTool.cpp @@ -270,7 +270,7 @@ void MemorySearcherTool::OnFilter(wxCommandEvent& event) void MemorySearcherTool::Load() { - const auto memorySearcherPath = ActiveSettings::GetPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); + const auto memorySearcherPath = ActiveSettings::GetUserDataPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); auto memSearcherIniContents = FileStream::LoadIntoMemory(memorySearcherPath); if (!memSearcherIniContents) return; @@ -322,7 +322,7 @@ void MemorySearcherTool::Load() void MemorySearcherTool::Save() { - const auto memorySearcherPath = ActiveSettings::GetPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); + const auto memorySearcherPath = ActiveSettings::GetUserDataPath("memorySearcher/{:016x}.ini", CafeSystem::GetForegroundTitleId()); FileStream* fs = FileStream::createFile2(memorySearcherPath); if (fs) { diff --git a/src/gui/debugger/DebuggerWindow2.cpp b/src/gui/debugger/DebuggerWindow2.cpp index 1f6c5f79..6263f0b7 100644 --- a/src/gui/debugger/DebuggerWindow2.cpp +++ b/src/gui/debugger/DebuggerWindow2.cpp @@ -271,7 +271,7 @@ DebuggerWindow2::DebuggerWindow2(wxFrame& parent, const wxRect& display_size) { 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.Load(); @@ -471,7 +471,7 @@ bool DebuggerWindow2::Show(bool show) std::wstring DebuggerWindow2::GetModuleStoragePath(std::string module_name, uint32_t crc_hash) const { 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) diff --git a/src/gui/input/InputSettings2.cpp b/src/gui/input/InputSettings2.cpp index 37bd604f..095aa52a 100644 --- a/src/gui/input/InputSettings2.cpp +++ b/src/gui/input/InputSettings2.cpp @@ -665,10 +665,10 @@ void InputSettings2::on_profile_delete(wxCommandEvent& event) } try { - const fs::path old_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}.txt", selection)); + const fs::path old_path = ActiveSettings::GetConfigPath("controllerProfiles/{}.txt", selection); fs::remove(old_path); - const fs::path path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}.xml", selection)); + const fs::path path = ActiveSettings::GetConfigPath("controllerProfiles/{}.xml", selection); fs::remove(path); profile_names->ChangeValue(kDefaultProfileName); diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp index 4ae43ce3..0861ba28 100644 --- a/src/input/InputManager.cpp +++ b/src/input/InputManager.cpp @@ -76,9 +76,9 @@ bool InputManager::load(size_t player_index, std::string_view filename) { fs::path file_path; if (filename.empty()) - file_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}", player_index)); + file_path = ActiveSettings::GetConfigPath("controllerProfiles/controller{}", player_index); else - file_path = ActiveSettings::GetPath(fmt::format("controllerProfiles/{}", filename)); + file_path = ActiveSettings::GetConfigPath("controllerProfiles/{}", filename); auto old_file = file_path; 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) return false; - fs::path file_path = ActiveSettings::GetPath("controllerProfiles"); + fs::path file_path = ActiveSettings::GetConfigPath("controllerProfiles"); fs::create_directories(file_path); const auto is_default_file = filename.empty(); @@ -664,8 +664,8 @@ EmulatedControllerPtr InputManager::delete_controller(size_t player_index, bool if(delete_profile) { std::error_code ec{}; - fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec); - fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec); + fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.xml", player_index), ec); + fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.txt", player_index), ec); } return result; @@ -680,8 +680,8 @@ EmulatedControllerPtr InputManager::delete_controller(size_t player_index, bool controller = {}; std::error_code ec{}; - fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.xml", player_index)), ec); - fs::remove(ActiveSettings::GetPath(fmt::format("controllerProfiles/controller{}.txt", player_index)), ec); + fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.xml", player_index), ec); + fs::remove(ActiveSettings::GetConfigPath("controllerProfiles/controller{}.txt", player_index), ec); return result; } @@ -782,7 +782,7 @@ void InputManager::apply_game_profile() std::vector InputManager::get_profiles() { - const auto path = ActiveSettings::GetPath("controllerProfiles"); + const auto path = ActiveSettings::GetConfigPath("controllerProfiles"); if (!exists(path)) return {}; diff --git a/src/main.cpp b/src/main.cpp index 87243bb8..e1c8ca49 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -161,7 +161,7 @@ void _putenvSafe(const char* c) void reconfigureGLDrivers() { // 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; fs::create_directories(nvCacheDir, err); @@ -245,8 +245,6 @@ void unitTests() int mainEmulatorHLE() { - if (!TestWriteAccess(ActiveSettings::GetPath())) - 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(); // run a couple of tests if in non-release mode #ifdef CEMU_DEBUG_ASSERT @@ -267,7 +265,7 @@ int mainEmulatorHLE() // init Cafe system (todo - the stuff above should be part of this too) CafeSystem::Initialize(); // init title list - CafeTitleList::Initialize(ActiveSettings::GetPath("title_list_cache.xml")); + CafeTitleList::Initialize(ActiveSettings::GetUserDataPath("title_list_cache.xml")); for (auto& it : GetConfig().game_paths) CafeTitleList::AddScanPath(it); fs::path mlcPath = ActiveSettings::GetMlcPath(); @@ -281,8 +279,6 @@ int mainEmulatorHLE() CafeSaveList::SetMLCPath(mlcPath); CafeSaveList::Refresh(); } - // Create UI - gui_create(); return 0; } @@ -347,10 +343,8 @@ int wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ L SDL_SetMainReady(); if (!LaunchSettings::HandleCommandline(lpCmdLine)) return 0; - ActiveSettings::LoadOnce(); - NetworkConfig::LoadOnce(); - HandlePostUpdate(); - return mainEmulatorHLE(); + gui_create(); + return 0; } // entrypoint for debug builds with console @@ -359,10 +353,8 @@ int main(int argc, char* argv[]) SDL_SetMainReady(); if (!LaunchSettings::HandleCommandline(argc, argv)) return 0; - ActiveSettings::LoadOnce(); - NetworkConfig::LoadOnce(); - HandlePostUpdate(); - return mainEmulatorHLE(); + gui_create(); + return 0; } #else @@ -374,11 +366,8 @@ int main(int argc, char *argv[]) #endif if (!LaunchSettings::HandleCommandline(argc, argv)) return 0; - - ActiveSettings::LoadOnce(); - NetworkConfig::LoadOnce(); - HandlePostUpdate(); - return mainEmulatorHLE(); + gui_create(); + return 0; } #endif diff --git a/src/util/helpers/helpers.cpp b/src/util/helpers/helpers.cpp index 99712296..fefe7985 100644 --- a/src/util/helpers/helpers.cpp +++ b/src/util/helpers/helpers.cpp @@ -306,11 +306,10 @@ bool TestWriteAccess(const fs::path& p) } // make path relative to Cemu directory -fs::path MakeRelativePath(const fs::path& path) +fs::path MakeRelativePath(const fs::path& base, const fs::path& path) { try { - const fs::path base = ActiveSettings::GetPath(); return fs::relative(path, base); } catch (const std::exception&) diff --git a/src/util/helpers/helpers.h b/src/util/helpers/helpers.h index 6240d56a..f81e5964 100644 --- a/src/util/helpers/helpers.h +++ b/src/util/helpers/helpers.h @@ -52,7 +52,7 @@ uint32_t GetPhysicalCoreCount(); // Creates a temporary file to test for write access bool TestWriteAccess(const fs::path& p); -fs::path MakeRelativePath(const fs::path& path); +fs::path MakeRelativePath(const fs::path& base, const fs::path& path); #ifdef HAS_DIRECTINPUT bool GUIDFromString(const char* string, GUID& guid); diff --git a/src/util/libusbWrapper/libusbWrapper.cpp b/src/util/libusbWrapper/libusbWrapper.cpp index e1d72985..8420216d 100644 --- a/src/util/libusbWrapper/libusbWrapper.cpp +++ b/src/util/libusbWrapper/libusbWrapper.cpp @@ -18,7 +18,7 @@ void libusbWrapper::init() m_module = LoadLibraryW(L"libusb-1.0.dll"); if (!m_module) { - const auto path = ActiveSettings::GetPath("resources/libusb-1.0.dll"); + const auto path = ActiveSettings::GetDataPath("resources/libusb-1.0.dll"); m_module = LoadLibraryW(path.generic_wstring().c_str()); if (!m_module) {