Windows default to non-portable + Reworked MLC handling and related UI (#1252)

This commit is contained in:
Exzap 2024-07-23 03:13:36 +02:00 committed by GitHub
parent 7522c8470e
commit 64232ffdbd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 515 additions and 651 deletions

View file

@ -7,41 +7,47 @@
#include "config/LaunchSettings.h"
#include "util/helpers/helpers.h"
std::set<fs::path>
ActiveSettings::LoadOnce(
const fs::path& executablePath,
const fs::path& userDataPath,
const fs::path& configPath,
const fs::path& cachePath,
const fs::path& dataPath)
void ActiveSettings::SetPaths(bool isPortableMode,
const fs::path& executablePath,
const fs::path& userDataPath,
const fs::path& configPath,
const fs::path& cachePath,
const fs::path& dataPath,
std::set<fs::path>& failedWriteAccess)
{
cemu_assert_debug(!s_setPathsCalled); // can only change paths before loading
s_isPortableMode = isPortableMode;
s_executable_path = executablePath;
s_user_data_path = userDataPath;
s_config_path = configPath;
s_cache_path = cachePath;
s_data_path = dataPath;
std::set<fs::path> failed_write_access;
failedWriteAccess.clear();
for (auto&& path : {userDataPath, configPath, cachePath})
{
if (!fs::exists(path))
{
std::error_code ec;
std::error_code ec;
if (!fs::exists(path, ec))
fs::create_directories(path, ec);
}
if (!TestWriteAccess(path))
{
cemuLog_log(LogType::Force, "Failed to write to {}", _pathToUtf8(path));
failed_write_access.insert(path);
failedWriteAccess.insert(path);
}
}
s_executable_filename = s_executable_path.filename();
s_setPathsCalled = true;
}
g_config.SetFilename(GetConfigPath("settings.xml").generic_wstring());
g_config.Load();
[[nodiscard]] bool ActiveSettings::IsPortableMode()
{
return s_isPortableMode;
}
void ActiveSettings::Init()
{
cemu_assert_debug(s_setPathsCalled);
std::string additionalErrorInfo;
s_has_required_online_files = iosuCrypt_checkRequirementsForOnlineMode(additionalErrorInfo) == IOS_CRYPTO_ONLINE_REQ_OK;
return failed_write_access;
}
bool ActiveSettings::LoadSharedLibrariesEnabled()
@ -229,6 +235,7 @@ bool ActiveSettings::ForceSamplerRoundToPrecision()
fs::path ActiveSettings::GetMlcPath()
{
cemu_assert_debug(s_setPathsCalled);
if(const auto launch_mlc = LaunchSettings::GetMLCPath(); launch_mlc.has_value())
return launch_mlc.value();
@ -238,6 +245,17 @@ fs::path ActiveSettings::GetMlcPath()
return GetDefaultMLCPath();
}
bool ActiveSettings::IsCustomMlcPath()
{
cemu_assert_debug(s_setPathsCalled);
return !GetConfig().mlc_path.GetValue().empty();
}
bool ActiveSettings::IsCommandLineMlcPath()
{
return LaunchSettings::GetMLCPath().has_value();
}
fs::path ActiveSettings::GetDefaultMLCPath()
{
return GetUserDataPath("mlc01");

View file

@ -34,12 +34,16 @@ private:
public:
// Set directories and return all directories that failed write access test
static std::set<fs::path>
LoadOnce(const fs::path& executablePath,
const fs::path& userDataPath,
const fs::path& configPath,
const fs::path& cachePath,
const fs::path& dataPath);
static void
SetPaths(bool isPortableMode,
const fs::path& executablePath,
const fs::path& userDataPath,
const fs::path& configPath,
const fs::path& cachePath,
const fs::path& dataPath,
std::set<fs::path>& failedWriteAccess);
static void Init();
[[nodiscard]] static fs::path GetExecutablePath() { return s_executable_path; }
[[nodiscard]] static fs::path GetExecutableFilename() { return s_executable_filename; }
@ -56,11 +60,14 @@ public:
template <typename ...TArgs>
[[nodiscard]] static fs::path GetMlcPath(TArgs&&... args){ return GetPath(GetMlcPath(), std::forward<TArgs>(args)...); };
static bool IsCustomMlcPath();
static bool IsCommandLineMlcPath();
// get mlc path to default cemu root dir/mlc01
[[nodiscard]] static fs::path GetDefaultMLCPath();
private:
inline static bool s_isPortableMode{false};
inline static fs::path s_executable_path;
inline static fs::path s_user_data_path;
inline static fs::path s_config_path;
@ -70,6 +77,9 @@ private:
inline static fs::path s_mlc_path;
public:
// can be called before Init
[[nodiscard]] static bool IsPortableMode();
// general
[[nodiscard]] static bool LoadSharedLibrariesEnabled();
[[nodiscard]] static bool DisplayDRCEnabled();
@ -111,6 +121,7 @@ public:
[[nodiscard]] static bool ForceSamplerRoundToPrecision();
private:
inline static bool s_setPathsCalled = false;
// dump options
inline static bool s_dump_shaders = false;
inline static bool s_dump_textures = false;

View file

@ -8,10 +8,6 @@ add_library(CemuConfig
LaunchSettings.h
NetworkSettings.cpp
NetworkSettings.h
PermanentConfig.cpp
PermanentConfig.h
PermanentStorage.cpp
PermanentStorage.h
XMLConfig.h
)

View file

@ -5,7 +5,6 @@
#include <wx/language.h>
#include "PermanentConfig.h"
#include "ActiveSettings.h"
XMLCemuConfig_t g_config(L"settings.xml");
@ -15,23 +14,6 @@ void CemuConfig::SetMLCPath(fs::path path, bool save)
mlc_path.SetValue(_pathToUtf8(path));
if(save)
g_config.Save();
// if custom mlc path has been selected, store it in permanent config
if (path != ActiveSettings::GetDefaultMLCPath())
{
try
{
auto pconfig = PermanentConfig::Load();
pconfig.custom_mlc_path = _pathToUtf8(path);
pconfig.Store();
}
catch (const PSDisabledException&) {}
catch (const std::exception& ex)
{
cemuLog_log(LogType::Force, "can't store custom mlc path in permanent storage: {}", ex.what());
}
}
Account::RefreshAccounts();
}

View file

@ -417,7 +417,7 @@ struct CemuConfig
ConfigValue<bool> save_screenshot{true};
ConfigValue<bool> did_show_vulkan_warning{false};
ConfigValue<bool> did_show_graphic_pack_download{false};
ConfigValue<bool> did_show_graphic_pack_download{false}; // no longer used but we keep the config value around in case people downgrade Cemu. Despite the name this was used for the Getting Started dialog
ConfigValue<bool> did_show_macos_disclaimer{false};
ConfigValue<bool> show_icon_column{ true };

View file

@ -1,65 +0,0 @@
#include "PermanentConfig.h"
#include "pugixml.hpp"
#include "PermanentStorage.h"
struct xml_string_writer : pugi::xml_writer
{
std::string result;
void write(const void* data, size_t size) override
{
result.append(static_cast<const char*>(data), size);
}
};
std::string PermanentConfig::ToXMLString() const noexcept
{
pugi::xml_document doc;
doc.append_child(pugi::node_declaration).append_attribute("encoding") = "UTF-8";
auto root = doc.append_child("config");
root.append_child("MlcPath").text().set(this->custom_mlc_path.c_str());
xml_string_writer writer;
doc.save(writer);
return writer.result;
}
PermanentConfig PermanentConfig::FromXMLString(std::string_view str) noexcept
{
PermanentConfig result{};
pugi::xml_document doc;
if(doc.load_buffer(str.data(), str.size()))
{
result.custom_mlc_path = doc.select_node("/config/MlcPath").node().text().as_string();
}
return result;
}
PermanentConfig PermanentConfig::Load()
{
PermanentStorage storage;
const auto str = storage.ReadFile(kFileName);
if (!str.empty())
return FromXMLString(str);
return {};
}
bool PermanentConfig::Store() noexcept
{
try
{
PermanentStorage storage;
storage.WriteStringToFile(kFileName, ToXMLString());
}
catch (...)
{
return false;
}
return true;
}

View file

@ -1,18 +0,0 @@
#pragma once
#include "PermanentStorage.h"
struct PermanentConfig
{
static constexpr const char* kFileName = "perm_setting.xml";
std::string custom_mlc_path;
[[nodiscard]] std::string ToXMLString() const noexcept;
static PermanentConfig FromXMLString(std::string_view str) noexcept;
// gets from permanent storage
static PermanentConfig Load();
// saves to permanent storage
bool Store() noexcept;
};

View file

@ -1,76 +0,0 @@
#include "PermanentStorage.h"
#include "config/CemuConfig.h"
#include "util/helpers/SystemException.h"
PermanentStorage::PermanentStorage()
{
if (!GetConfig().permanent_storage)
throw PSDisabledException();
const char* appdata = std::getenv("LOCALAPPDATA");
if (!appdata)
throw std::runtime_error("can't get LOCALAPPDATA");
m_storage_path = appdata;
m_storage_path /= "Cemu";
fs::create_directories(m_storage_path);
}
PermanentStorage::~PermanentStorage()
{
if (m_remove_storage)
{
std::error_code ec;
fs::remove_all(m_storage_path, ec);
if (ec)
{
SystemException ex(ec);
cemuLog_log(LogType::Force, "can't remove permanent storage: {}", ex.what());
}
}
}
void PermanentStorage::ClearAllFiles() const
{
fs::remove_all(m_storage_path);
fs::create_directories(m_storage_path);
}
void PermanentStorage::RemoveStorage()
{
m_remove_storage = true;
}
void PermanentStorage::WriteStringToFile(std::string_view filename, std::string_view content)
{
const auto name = m_storage_path.append(filename.data(), filename.data() + filename.size());
std::ofstream file(name.string());
file.write(content.data(), (uint32_t)content.size());
}
std::string PermanentStorage::ReadFile(std::string_view filename) noexcept
{
try
{
const auto name = m_storage_path.append(filename.data(), filename.data() + filename.size());
std::ifstream file(name, std::ios::in | std::ios::ate);
if (!file.is_open())
return {};
const auto end = file.tellg();
file.seekg(0, std::ios::beg);
const auto file_size = end - file.tellg();
if (file_size == 0)
return {};
std::string result;
result.resize(file_size);
file.read(result.data(), file_size);
return result;
}
catch (...)
{
return {};
}
}

View file

@ -1,27 +0,0 @@
#pragma once
// disabled by config
class PSDisabledException : public std::runtime_error
{
public:
PSDisabledException()
: std::runtime_error("permanent storage is disabled by user") {}
};
class PermanentStorage
{
public:
PermanentStorage();
~PermanentStorage();
void ClearAllFiles() const;
// flags storage to be removed on destruction
void RemoveStorage();
void WriteStringToFile(std::string_view filename, std::string_view content);
std::string ReadFile(std::string_view filename) noexcept;
private:
fs::path m_storage_path;
bool m_remove_storage = false;
};