6c8f2b355a
Completely removes code related to parsing the settings file on the java side. Now all settings are accessed via NativeConfig.kt and config.cpp has been modified to be closer to the core counterpart. Since the core currently uses QSettings, we can't remove reliance from Wini yet. This also includes simplifications to each settings interface to get closer to native code and prepare for per-game settings.
305 lines
9.0 KiB
C++
305 lines
9.0 KiB
C++
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <version>
|
|
#include "common/settings_enums.h"
|
|
#if __cpp_lib_chrono >= 201907L
|
|
#include <chrono>
|
|
#include <exception>
|
|
#include <stdexcept>
|
|
#endif
|
|
#include <compare>
|
|
#include <cstddef>
|
|
#include <filesystem>
|
|
#include <functional>
|
|
#include <string_view>
|
|
#include <type_traits>
|
|
#include <fmt/core.h>
|
|
|
|
#include "common/assert.h"
|
|
#include "common/fs/fs_util.h"
|
|
#include "common/fs/path_util.h"
|
|
#include "common/logging/log.h"
|
|
#include "common/settings.h"
|
|
#include "common/time_zone.h"
|
|
|
|
namespace Settings {
|
|
|
|
// Clang 14 and earlier have errors when explicitly instantiating these classes
|
|
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
|
#define SETTING(TYPE, RANGED) template class Setting<TYPE, RANGED>
|
|
#define SWITCHABLE(TYPE, RANGED) template class SwitchableSetting<TYPE, RANGED>
|
|
|
|
SETTING(AudioEngine, false);
|
|
SETTING(bool, false);
|
|
SETTING(int, false);
|
|
SETTING(std::string, false);
|
|
SETTING(u16, false);
|
|
SWITCHABLE(AnisotropyMode, true);
|
|
SWITCHABLE(AntiAliasing, false);
|
|
SWITCHABLE(AspectRatio, true);
|
|
SWITCHABLE(AstcDecodeMode, true);
|
|
SWITCHABLE(AstcRecompression, true);
|
|
SWITCHABLE(AudioMode, true);
|
|
SWITCHABLE(CpuAccuracy, true);
|
|
SWITCHABLE(FullscreenMode, true);
|
|
SWITCHABLE(GpuAccuracy, true);
|
|
SWITCHABLE(Language, true);
|
|
SWITCHABLE(NvdecEmulation, false);
|
|
SWITCHABLE(Region, true);
|
|
SWITCHABLE(RendererBackend, true);
|
|
SWITCHABLE(ScalingFilter, false);
|
|
SWITCHABLE(ShaderBackend, true);
|
|
SWITCHABLE(TimeZone, true);
|
|
SETTING(VSyncMode, true);
|
|
SWITCHABLE(bool, false);
|
|
SWITCHABLE(int, false);
|
|
SWITCHABLE(int, true);
|
|
SWITCHABLE(s64, false);
|
|
SWITCHABLE(u16, true);
|
|
SWITCHABLE(u32, false);
|
|
SWITCHABLE(u8, false);
|
|
SWITCHABLE(u8, true);
|
|
|
|
#undef SETTING
|
|
#undef SWITCHABLE
|
|
#endif
|
|
|
|
Values values;
|
|
|
|
std::string GetTimeZoneString(TimeZone time_zone) {
|
|
const auto time_zone_index = static_cast<std::size_t>(time_zone);
|
|
ASSERT(time_zone_index < Common::TimeZone::GetTimeZoneStrings().size());
|
|
|
|
std::string location_name;
|
|
if (time_zone_index == 0) { // Auto
|
|
#if __cpp_lib_chrono >= 201907L && !defined(MINGW)
|
|
// Disabled for MinGW -- tzdb always returns Etc/UTC
|
|
try {
|
|
const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb();
|
|
const std::chrono::time_zone* current_zone = time_zone_data.current_zone();
|
|
std::string_view current_zone_name = current_zone->name();
|
|
location_name = current_zone_name;
|
|
} catch (std::runtime_error& runtime_error) {
|
|
// VCRUNTIME will throw a runtime_error if the operating system's selected time zone
|
|
// cannot be found
|
|
location_name = Common::TimeZone::FindSystemTimeZone();
|
|
LOG_WARNING(Common,
|
|
"Error occurred when trying to determine system time zone:\n{}\nFalling "
|
|
"back to hour offset \"{}\"",
|
|
runtime_error.what(), location_name);
|
|
}
|
|
#else
|
|
location_name = Common::TimeZone::FindSystemTimeZone();
|
|
#endif
|
|
} else {
|
|
location_name = Common::TimeZone::GetTimeZoneStrings()[time_zone_index];
|
|
}
|
|
return location_name;
|
|
}
|
|
|
|
void LogSettings() {
|
|
const auto log_setting = [](std::string_view name, const auto& value) {
|
|
LOG_INFO(Config, "{}: {}", name, value);
|
|
};
|
|
|
|
const auto log_path = [](std::string_view name, const std::filesystem::path& path) {
|
|
LOG_INFO(Config, "{}: {}", name, Common::FS::PathToUTF8String(path));
|
|
};
|
|
|
|
LOG_INFO(Config, "yuzu Configuration:");
|
|
for (auto& [category, settings] : values.linkage.by_category) {
|
|
for (const auto& setting : settings) {
|
|
if (setting->Id() == values.yuzu_token.Id()) {
|
|
// Hide the token secret, for security reasons.
|
|
continue;
|
|
}
|
|
|
|
const auto name = fmt::format(
|
|
"{:c}{:c} {}.{}", setting->ToString() == setting->DefaultToString() ? '-' : 'M',
|
|
setting->UsingGlobal() ? '-' : 'C', TranslateCategory(category),
|
|
setting->GetLabel());
|
|
|
|
log_setting(name, setting->Canonicalize());
|
|
}
|
|
}
|
|
log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir));
|
|
log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir));
|
|
log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir));
|
|
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
|
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
|
|
}
|
|
|
|
bool IsGPULevelExtreme() {
|
|
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme;
|
|
}
|
|
|
|
bool IsGPULevelHigh() {
|
|
return values.gpu_accuracy.GetValue() == GpuAccuracy::Extreme ||
|
|
values.gpu_accuracy.GetValue() == GpuAccuracy::High;
|
|
}
|
|
|
|
bool IsFastmemEnabled() {
|
|
if (values.cpu_debug_mode) {
|
|
return static_cast<bool>(values.cpuopt_fastmem);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IsDockedMode() {
|
|
return values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
|
|
}
|
|
|
|
float Volume() {
|
|
if (values.audio_muted) {
|
|
return 0.0f;
|
|
}
|
|
return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault());
|
|
}
|
|
|
|
const char* TranslateCategory(Category category) {
|
|
switch (category) {
|
|
case Category::Android:
|
|
return "Android";
|
|
case Category::Audio:
|
|
return "Audio";
|
|
case Category::Core:
|
|
return "Core";
|
|
case Category::Cpu:
|
|
case Category::CpuDebug:
|
|
case Category::CpuUnsafe:
|
|
return "Cpu";
|
|
case Category::Renderer:
|
|
case Category::RendererAdvanced:
|
|
case Category::RendererDebug:
|
|
return "Renderer";
|
|
case Category::System:
|
|
case Category::SystemAudio:
|
|
return "System";
|
|
case Category::DataStorage:
|
|
return "Data Storage";
|
|
case Category::Debugging:
|
|
case Category::DebuggingGraphics:
|
|
return "Debugging";
|
|
case Category::Miscellaneous:
|
|
return "Miscellaneous";
|
|
case Category::Network:
|
|
return "Network";
|
|
case Category::WebService:
|
|
return "WebService";
|
|
case Category::AddOns:
|
|
return "DisabledAddOns";
|
|
case Category::Controls:
|
|
return "Controls";
|
|
case Category::Ui:
|
|
case Category::UiGeneral:
|
|
return "UI";
|
|
case Category::UiLayout:
|
|
return "UiLayout";
|
|
case Category::UiGameList:
|
|
return "UiGameList";
|
|
case Category::Screenshots:
|
|
return "Screenshots";
|
|
case Category::Shortcuts:
|
|
return "Shortcuts";
|
|
case Category::Multiplayer:
|
|
return "Multiplayer";
|
|
case Category::Services:
|
|
return "Services";
|
|
case Category::Paths:
|
|
return "Paths";
|
|
case Category::MaxEnum:
|
|
break;
|
|
}
|
|
return "Miscellaneous";
|
|
}
|
|
|
|
void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info) {
|
|
info.downscale = false;
|
|
switch (setup) {
|
|
case ResolutionSetup::Res1_2X:
|
|
info.up_scale = 1;
|
|
info.down_shift = 1;
|
|
info.downscale = true;
|
|
break;
|
|
case ResolutionSetup::Res3_4X:
|
|
info.up_scale = 3;
|
|
info.down_shift = 2;
|
|
info.downscale = true;
|
|
break;
|
|
case ResolutionSetup::Res1X:
|
|
info.up_scale = 1;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res3_2X:
|
|
info.up_scale = 3;
|
|
info.down_shift = 1;
|
|
break;
|
|
case ResolutionSetup::Res2X:
|
|
info.up_scale = 2;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res3X:
|
|
info.up_scale = 3;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res4X:
|
|
info.up_scale = 4;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res5X:
|
|
info.up_scale = 5;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res6X:
|
|
info.up_scale = 6;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res7X:
|
|
info.up_scale = 7;
|
|
info.down_shift = 0;
|
|
break;
|
|
case ResolutionSetup::Res8X:
|
|
info.up_scale = 8;
|
|
info.down_shift = 0;
|
|
break;
|
|
default:
|
|
ASSERT(false);
|
|
info.up_scale = 1;
|
|
info.down_shift = 0;
|
|
break;
|
|
}
|
|
info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift);
|
|
info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale;
|
|
info.active = info.up_scale != 1 || info.down_shift != 0;
|
|
}
|
|
|
|
void UpdateRescalingInfo() {
|
|
const auto setup = values.resolution_setup.GetValue();
|
|
auto& info = values.resolution_info;
|
|
TranslateResolutionInfo(setup, info);
|
|
}
|
|
|
|
void RestoreGlobalState(bool is_powered_on) {
|
|
// If a game is running, DO NOT restore the global settings state
|
|
if (is_powered_on) {
|
|
return;
|
|
}
|
|
|
|
for (const auto& reset : values.linkage.restore_functions) {
|
|
reset();
|
|
}
|
|
}
|
|
|
|
static bool configuring_global = true;
|
|
|
|
bool IsConfiguringGlobal() {
|
|
return configuring_global;
|
|
}
|
|
|
|
void SetConfiguringGlobal(bool is_global) {
|
|
configuring_global = is_global;
|
|
}
|
|
|
|
} // namespace Settings
|