mirror of
https://github.com/pound-emu/pound.git
synced 2025-12-23 16:37:00 +00:00
a
This commit is contained in:
parent
bc0f05735c
commit
824f59de3b
7 changed files with 2515 additions and 3 deletions
530
common/polyfill_ranges.h
Executable file
530
common/polyfill_ranges.h
Executable file
|
|
@ -0,0 +1,530 @@
|
|||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
//
|
||||
// TODO: remove this file when ranges are supported by all compilation targets
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <version>
|
||||
|
||||
#ifndef __cpp_lib_ranges
|
||||
|
||||
namespace std {
|
||||
namespace ranges {
|
||||
|
||||
template <typename T>
|
||||
concept range = requires(T& t) {
|
||||
begin(t);
|
||||
end(t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept input_range = range<T>;
|
||||
|
||||
template <typename T>
|
||||
concept output_range = range<T>;
|
||||
|
||||
template <range R>
|
||||
using range_difference_t = ptrdiff_t;
|
||||
|
||||
//
|
||||
// find, find_if, find_if_not
|
||||
//
|
||||
|
||||
struct find_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value,
|
||||
Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(proj, *first) == value) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct find_if_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(pred, std::invoke(proj, *first))) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct find_if_not_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (!std::invoke(pred, std::invoke(proj, *first))) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr find_fn find;
|
||||
inline constexpr find_if_fn find_if;
|
||||
inline constexpr find_if_not_fn find_if_not;
|
||||
|
||||
//
|
||||
// any_of, all_of, none_of
|
||||
//
|
||||
|
||||
struct all_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct any_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct none_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr any_of_fn any_of;
|
||||
inline constexpr all_of_fn all_of;
|
||||
inline constexpr none_of_fn none_of;
|
||||
|
||||
//
|
||||
// count, count_if
|
||||
//
|
||||
|
||||
struct count_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity>
|
||||
constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value,
|
||||
Proj proj = {}) const {
|
||||
ptrdiff_t counter = 0;
|
||||
for (; first != last; ++first)
|
||||
if (std::invoke(proj, *first) == value)
|
||||
++counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity>
|
||||
constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct count_if_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
ptrdiff_t counter = 0;
|
||||
for (; first != last; ++first)
|
||||
if (std::invoke(pred, std::invoke(proj, *first)))
|
||||
++counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr count_fn count;
|
||||
inline constexpr count_if_fn count_if;
|
||||
|
||||
//
|
||||
// transform
|
||||
//
|
||||
|
||||
struct transform_fn {
|
||||
template <typename InputIterator, typename OutputIterator, typename F,
|
||||
typename Proj = std::identity>
|
||||
constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result,
|
||||
F op, Proj proj = {}) const {
|
||||
for (; first1 != last1; ++first1, (void)++result) {
|
||||
*result = std::invoke(op, std::invoke(proj, *first1));
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator, typename F,
|
||||
typename Proj = std::identity>
|
||||
constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr transform_fn transform;
|
||||
|
||||
//
|
||||
// sort
|
||||
//
|
||||
|
||||
struct sort_fn {
|
||||
template <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity>
|
||||
constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const {
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
Iterator last_iter = ranges::next(first, last);
|
||||
std::sort(first, last_iter,
|
||||
[&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); });
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity>
|
||||
constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr sort_fn sort;
|
||||
|
||||
//
|
||||
// fill
|
||||
//
|
||||
|
||||
struct fill_fn {
|
||||
template <typename T, typename OutputIterator>
|
||||
constexpr OutputIterator operator()(OutputIterator first, OutputIterator last,
|
||||
const T& value) const {
|
||||
while (first != last) {
|
||||
*first++ = value;
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename T, ranges::output_range R>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value);
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr fill_fn fill;
|
||||
|
||||
//
|
||||
// for_each
|
||||
//
|
||||
|
||||
struct for_each_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Fun>
|
||||
constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
std::invoke(f, std::invoke(proj, *first));
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Fun>
|
||||
constexpr void operator()(R&& r, Fun f, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr for_each_fn for_each;
|
||||
|
||||
//
|
||||
// min_element, max_element
|
||||
//
|
||||
|
||||
struct min_element_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
auto smallest = first;
|
||||
++first;
|
||||
for (; first != last; ++first) {
|
||||
if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) {
|
||||
smallest = first;
|
||||
}
|
||||
}
|
||||
return smallest;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct max_element_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
auto largest = first;
|
||||
++first;
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) {
|
||||
largest = first;
|
||||
}
|
||||
}
|
||||
return largest;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr min_element_fn min_element;
|
||||
inline constexpr max_element_fn max_element;
|
||||
|
||||
//
|
||||
// replace, replace_if
|
||||
//
|
||||
|
||||
struct replace_fn {
|
||||
template <typename Iterator, typename T1, typename T2, typename Proj = std::identity>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value,
|
||||
const T2& new_value, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (old_value == std::invoke(proj, *first)) {
|
||||
*first = new_value;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T1& old_value, const T2& new_value,
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct replace_if_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value,
|
||||
Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (!!std::invoke(pred, std::invoke(proj, *first))) {
|
||||
*first = new_value;
|
||||
}
|
||||
}
|
||||
return std::move(first);
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, const T& new_value,
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value,
|
||||
std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr replace_fn replace;
|
||||
inline constexpr replace_if_fn replace_if;
|
||||
|
||||
//
|
||||
// copy, copy_if
|
||||
//
|
||||
|
||||
struct copy_fn {
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
constexpr void operator()(InputIterator first, InputIterator last,
|
||||
OutputIterator result) const {
|
||||
for (; first != last; ++first, (void)++result) {
|
||||
*result = *first;
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator>
|
||||
constexpr void operator()(R&& r, OutputIterator result) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(result));
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_if_fn {
|
||||
template <typename InputIterator, typename OutputIterator, typename Proj = std::identity,
|
||||
typename Pred>
|
||||
constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result,
|
||||
Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(pred, std::invoke(proj, *first))) {
|
||||
*result = *first;
|
||||
++result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator, typename Proj = std::identity,
|
||||
typename Pred>
|
||||
constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred),
|
||||
std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr copy_fn copy;
|
||||
inline constexpr copy_if_fn copy_if;
|
||||
|
||||
//
|
||||
// generate
|
||||
//
|
||||
|
||||
struct generate_fn {
|
||||
template <typename Iterator, typename F>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, F gen) const {
|
||||
for (; first != last; *first = std::invoke(gen), ++first)
|
||||
;
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename R, std::copy_constructible F>
|
||||
requires std::invocable<F&> && ranges::output_range<R>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(gen));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr generate_fn generate;
|
||||
|
||||
//
|
||||
// lower_bound, upper_bound
|
||||
//
|
||||
|
||||
struct lower_bound_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
Iterator it;
|
||||
std::ptrdiff_t _count, _step;
|
||||
_count = std::distance(first, last);
|
||||
|
||||
while (_count > 0) {
|
||||
it = first;
|
||||
_step = _count / 2;
|
||||
ranges::advance(it, _step, last);
|
||||
if (comp(std::invoke(proj, *it), value)) {
|
||||
first = ++it;
|
||||
_count -= _step + 1;
|
||||
} else {
|
||||
_count = _step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct upper_bound_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
Iterator it;
|
||||
std::ptrdiff_t _count, _step;
|
||||
_count = std::distance(first, last);
|
||||
|
||||
while (_count > 0) {
|
||||
it = first;
|
||||
_step = _count / 2;
|
||||
ranges::advance(it, _step, last);
|
||||
if (!comp(value, std::invoke(proj, *it))) {
|
||||
first = ++it;
|
||||
_count -= _step + 1;
|
||||
} else {
|
||||
_count = _step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr lower_bound_fn lower_bound;
|
||||
inline constexpr upper_bound_fn upper_bound;
|
||||
|
||||
//
|
||||
// adjacent_find
|
||||
//
|
||||
|
||||
struct adjacent_find_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last)
|
||||
return first;
|
||||
auto _next = ranges::next(first);
|
||||
for (; _next != last; ++_next, ++first)
|
||||
if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next)))
|
||||
return first;
|
||||
return _next;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity,
|
||||
typename Pred = ranges::equal_to>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr adjacent_find_fn adjacent_find;
|
||||
|
||||
} // namespace ranges
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
650
common/settings.h
Executable file
650
common/settings.h
Executable file
|
|
@ -0,0 +1,650 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common_types.h"
|
||||
#include "settings_common.h"
|
||||
#include "settings_enums.h"
|
||||
#include "settings_input.h"
|
||||
#include "settings_setting.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
const char* TranslateCategory(Settings::Category category);
|
||||
|
||||
struct ResolutionScalingInfo {
|
||||
u32 up_scale{1};
|
||||
u32 down_shift{0};
|
||||
f32 up_factor{1.0f};
|
||||
f32 down_factor{1.0f};
|
||||
bool active{};
|
||||
bool downscale{};
|
||||
|
||||
s32 ScaleUp(s32 value) const {
|
||||
if (value == 0) {
|
||||
return 0;
|
||||
}
|
||||
return std::max((value * static_cast<s32>(up_scale)) >> static_cast<s32>(down_shift), 1);
|
||||
}
|
||||
|
||||
u32 ScaleUp(u32 value) const {
|
||||
if (value == 0U) {
|
||||
return 0U;
|
||||
}
|
||||
return std::max((value * up_scale) >> down_shift, 1U);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef CANNOT_EXPLICITLY_INSTANTIATE
|
||||
// Instantiate the classes elsewhere (settings.cpp) to reduce compiler/linker work
|
||||
#define SETTING(TYPE, RANGED) extern template class Setting<TYPE, RANGED>
|
||||
#define SWITCHABLE(TYPE, RANGED) extern template class SwitchableSetting<TYPE, RANGED>
|
||||
|
||||
SETTING(AudioEngine, false);
|
||||
SETTING(bool, false);
|
||||
SETTING(int, false);
|
||||
SETTING(s32, false);
|
||||
SETTING(std::string, 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(CpuBackend, true);
|
||||
SWITCHABLE(CpuAccuracy, true);
|
||||
SWITCHABLE(FullscreenMode, true);
|
||||
SWITCHABLE(GpuAccuracy, true);
|
||||
SWITCHABLE(Language, true);
|
||||
SWITCHABLE(MemoryLayout, 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);
|
||||
|
||||
// Used in UISettings
|
||||
// TODO see if we can move this to uisettings.h
|
||||
SWITCHABLE(ConfirmStop, true);
|
||||
|
||||
#undef SETTING
|
||||
#undef SWITCHABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The InputSetting class allows for getting a reference to either the global or custom members.
|
||||
* This is required as we cannot easily modify the values of user-defined types within containers
|
||||
* using the SetValue() member function found in the Setting class. The primary purpose of this
|
||||
* class is to store an array of 10 PlayerInput structs for both the global and custom setting and
|
||||
* allows for easily accessing and modifying both settings.
|
||||
*/
|
||||
template <typename Type>
|
||||
class InputSetting final {
|
||||
public:
|
||||
InputSetting() = default;
|
||||
explicit InputSetting(Type val) : Setting<Type>(val) {}
|
||||
~InputSetting() = default;
|
||||
void SetGlobal(bool to_global) {
|
||||
use_global = to_global;
|
||||
}
|
||||
[[nodiscard]] bool UsingGlobal() const {
|
||||
return use_global;
|
||||
}
|
||||
[[nodiscard]] Type& GetValue(bool need_global = false) {
|
||||
if (use_global || need_global) {
|
||||
return global;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_global{true}; ///< The setting's global state
|
||||
Type global{}; ///< The setting
|
||||
Type custom{}; ///< The custom setting value
|
||||
};
|
||||
|
||||
struct TouchFromButtonMap {
|
||||
std::string name;
|
||||
std::vector<std::string> buttons;
|
||||
};
|
||||
|
||||
struct Values {
|
||||
Linkage linkage{};
|
||||
|
||||
// Applet
|
||||
Setting<AppletMode> cabinet_applet_mode{linkage, AppletMode::LLE, "cabinet_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> controller_applet_mode{linkage, AppletMode::HLE, "controller_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> data_erase_applet_mode{linkage, AppletMode::HLE, "data_erase_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> error_applet_mode{linkage, AppletMode::LLE, "error_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::HLE, "net_connect_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> player_select_applet_mode{
|
||||
linkage, AppletMode::HLE, "player_select_applet_mode", Category::LibraryApplet};
|
||||
Setting<AppletMode> swkbd_applet_mode{linkage, AppletMode::LLE, "swkbd_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> mii_edit_applet_mode{linkage, AppletMode::LLE, "mii_edit_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> web_applet_mode{linkage, AppletMode::HLE, "web_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> shop_applet_mode{linkage, AppletMode::HLE, "shop_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> photo_viewer_applet_mode{
|
||||
linkage, AppletMode::LLE, "photo_viewer_applet_mode", Category::LibraryApplet};
|
||||
Setting<AppletMode> offline_web_applet_mode{linkage, AppletMode::LLE, "offline_web_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> login_share_applet_mode{linkage, AppletMode::HLE, "login_share_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
Setting<AppletMode> wifi_web_auth_applet_mode{
|
||||
linkage, AppletMode::HLE, "wifi_web_auth_applet_mode", Category::LibraryApplet};
|
||||
Setting<AppletMode> my_page_applet_mode{linkage, AppletMode::LLE, "my_page_applet_mode",
|
||||
Category::LibraryApplet};
|
||||
|
||||
// Audio
|
||||
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
||||
Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_output_device_id{
|
||||
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_input_device_id{
|
||||
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioMode, true> sound_index{
|
||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||
true};
|
||||
SwitchableSetting<u8, true> volume{linkage,
|
||||
100,
|
||||
0,
|
||||
200,
|
||||
"volume",
|
||||
Category::Audio,
|
||||
Specialization::Scalar | Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
Setting<bool, false> audio_muted{
|
||||
linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true};
|
||||
Setting<bool, false> dump_audio_commands{
|
||||
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
||||
|
||||
// Core
|
||||
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
|
||||
SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage,
|
||||
MemoryLayout::Memory_4Gb,
|
||||
MemoryLayout::Memory_4Gb,
|
||||
MemoryLayout::Memory_8Gb,
|
||||
"memory_layout_mode",
|
||||
Category::Core};
|
||||
SwitchableSetting<bool> use_speed_limit{
|
||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, false, true};
|
||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||
100,
|
||||
0,
|
||||
9999,
|
||||
"speed_limit",
|
||||
Category::Core,
|
||||
Specialization::Countable | Specialization::Percentage,
|
||||
true,
|
||||
true,
|
||||
&use_speed_limit};
|
||||
|
||||
// Cpu
|
||||
SwitchableSetting<CpuBackend, true> cpu_backend{linkage,
|
||||
#ifdef HAS_NCE
|
||||
CpuBackend::Nce,
|
||||
#else
|
||||
CpuBackend::Dynarmic,
|
||||
#endif
|
||||
CpuBackend::Dynarmic,
|
||||
#ifdef HAS_NCE
|
||||
CpuBackend::Nce,
|
||||
#else
|
||||
CpuBackend::Dynarmic,
|
||||
#endif
|
||||
"cpu_backend",
|
||||
Category::Cpu};
|
||||
SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
|
||||
CpuAccuracy::Auto, CpuAccuracy::Paranoid,
|
||||
"cpu_accuracy", Category::Cpu};
|
||||
SwitchableSetting<bool> cpu_debug_mode{linkage, false, "cpu_debug_mode", Category::CpuDebug};
|
||||
|
||||
Setting<bool> cpuopt_page_tables{linkage, true, "cpuopt_page_tables", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_block_linking{linkage, true, "cpuopt_block_linking", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_return_stack_buffer{linkage, true, "cpuopt_return_stack_buffer",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_fast_dispatcher{linkage, true, "cpuopt_fast_dispatcher",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_context_elimination{linkage, true, "cpuopt_context_elimination",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_const_prop{linkage, true, "cpuopt_const_prop", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_misc_ir{linkage, true, "cpuopt_misc_ir", Category::CpuDebug};
|
||||
Setting<bool> cpuopt_reduce_misalign_checks{linkage, true, "cpuopt_reduce_misalign_checks",
|
||||
Category::CpuDebug};
|
||||
SwitchableSetting<bool> cpuopt_fastmem{linkage, true, "cpuopt_fastmem", Category::CpuDebug};
|
||||
SwitchableSetting<bool> cpuopt_fastmem_exclusives{linkage, true, "cpuopt_fastmem_exclusives",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_recompile_exclusives{linkage, true, "cpuopt_recompile_exclusives",
|
||||
Category::CpuDebug};
|
||||
Setting<bool> cpuopt_ignore_memory_aborts{linkage, true, "cpuopt_ignore_memory_aborts",
|
||||
Category::CpuDebug};
|
||||
|
||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{linkage, true, "cpuopt_unsafe_unfuse_fma",
|
||||
Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{
|
||||
linkage, true, "cpuopt_unsafe_reduce_fp_error", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_standard_fpcr{
|
||||
linkage, true, "cpuopt_unsafe_ignore_standard_fpcr", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_inaccurate_nan{
|
||||
linkage, true, "cpuopt_unsafe_inaccurate_nan", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_fastmem_check{
|
||||
linkage, true, "cpuopt_unsafe_fastmem_check", Category::CpuUnsafe};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_ignore_global_monitor{
|
||||
linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe};
|
||||
|
||||
// Renderer
|
||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null,
|
||||
"backend", Category::Renderer};
|
||||
SwitchableSetting<ShaderBackend, true> shader_backend{
|
||||
linkage, ShaderBackend::Glsl, ShaderBackend::Glsl, ShaderBackend::SpirV,
|
||||
"shader_backend", Category::Renderer, Specialization::RuntimeList};
|
||||
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
|
||||
Specialization::RuntimeList};
|
||||
|
||||
SwitchableSetting<bool> use_disk_shader_cache{linkage, true, "use_disk_shader_cache",
|
||||
Category::Renderer};
|
||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{
|
||||
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
|
||||
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
|
||||
#ifdef ANDROID
|
||||
AstcDecodeMode::Cpu,
|
||||
#else
|
||||
AstcDecodeMode::Gpu,
|
||||
#endif
|
||||
AstcDecodeMode::Cpu,
|
||||
AstcDecodeMode::CpuAsynchronous,
|
||||
"accelerate_astc",
|
||||
Category::Renderer};
|
||||
SwitchableSetting<VSyncMode, true> vsync_mode{
|
||||
linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed,
|
||||
"use_vsync", Category::Renderer, Specialization::RuntimeList, true,
|
||||
true};
|
||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu,
|
||||
"nvdec_emulation", Category::Renderer};
|
||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||
// Default to exclusive fullscreen on these platforms for now.
|
||||
SwitchableSetting<FullscreenMode, true> fullscreen_mode{linkage,
|
||||
#ifdef _WIN32
|
||||
FullscreenMode::Borderless,
|
||||
#else
|
||||
FullscreenMode::Exclusive,
|
||||
#endif
|
||||
FullscreenMode::Borderless,
|
||||
FullscreenMode::Exclusive,
|
||||
"fullscreen_mode",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<AspectRatio, true> aspect_ratio{linkage,
|
||||
AspectRatio::R16_9,
|
||||
AspectRatio::R16_9,
|
||||
AspectRatio::Stretch,
|
||||
"aspect_ratio",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
|
||||
ResolutionScalingInfo resolution_info{};
|
||||
SwitchableSetting<ResolutionSetup> resolution_setup{linkage, ResolutionSetup::Res1X,
|
||||
"resolution_setup", Category::Renderer};
|
||||
SwitchableSetting<ScalingFilter> scaling_filter{linkage,
|
||||
ScalingFilter::Bilinear,
|
||||
"scaling_filter",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<AntiAliasing> anti_aliasing{linkage,
|
||||
AntiAliasing::None,
|
||||
"anti_aliasing",
|
||||
Category::Renderer,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
||||
25,
|
||||
0,
|
||||
200,
|
||||
"fsr_sharpening_slider",
|
||||
Category::Renderer,
|
||||
Specialization::Scalar |
|
||||
Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
|
||||
SwitchableSetting<u8, false> bg_red{
|
||||
linkage, 0, "bg_red", Category::Renderer, Specialization::Default, true, true};
|
||||
SwitchableSetting<u8, false> bg_green{
|
||||
linkage, 0, "bg_green", Category::Renderer, Specialization::Default, true, true};
|
||||
SwitchableSetting<u8, false> bg_blue{
|
||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||
|
||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||
#ifdef ANDROID
|
||||
GpuAccuracy::Normal,
|
||||
#else
|
||||
GpuAccuracy::High,
|
||||
#endif
|
||||
GpuAccuracy::Normal,
|
||||
GpuAccuracy::Extreme,
|
||||
"gpu_accuracy",
|
||||
Category::RendererAdvanced,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
GpuAccuracy current_gpu_accuracy{GpuAccuracy::High};
|
||||
SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
|
||||
#ifdef ANDROID
|
||||
AnisotropyMode::Default,
|
||||
#else
|
||||
AnisotropyMode::Automatic,
|
||||
#endif
|
||||
AnisotropyMode::Automatic,
|
||||
AnisotropyMode::X16,
|
||||
"max_anisotropy",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
|
||||
AstcRecompression::Uncompressed,
|
||||
AstcRecompression::Uncompressed,
|
||||
AstcRecompression::Bc3,
|
||||
"astc_recompression",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<VramUsageMode, true> vram_usage_mode{linkage,
|
||||
VramUsageMode::Conservative,
|
||||
VramUsageMode::Conservative,
|
||||
VramUsageMode::Aggressive,
|
||||
"vram_usage_mode",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> async_presentation{linkage,
|
||||
#ifdef ANDROID
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
"async_presentation", Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> renderer_force_max_clock{linkage, false, "force_max_clock",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_reactive_flushing{linkage,
|
||||
#ifdef ANDROID
|
||||
false,
|
||||
#else
|
||||
true,
|
||||
#endif
|
||||
"use_reactive_flushing",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_fast_gpu_time{
|
||||
linkage, true, "use_fast_gpu_time", Category::RendererAdvanced, Specialization::Default,
|
||||
true, true};
|
||||
SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{linkage,
|
||||
true,
|
||||
"use_vulkan_driver_pipeline_cache",
|
||||
Category::RendererAdvanced,
|
||||
Specialization::Default,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<bool> enable_compute_pipelines{linkage, false, "enable_compute_pipelines",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> use_video_framerate{linkage, false, "use_video_framerate",
|
||||
Category::RendererAdvanced};
|
||||
SwitchableSetting<bool> barrier_feedback_loops{linkage, true, "barrier_feedback_loops",
|
||||
Category::RendererAdvanced};
|
||||
|
||||
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
|
||||
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
|
||||
Category::RendererDebug};
|
||||
Setting<bool> enable_nsight_aftermath{linkage, false, "nsight_aftermath",
|
||||
Category::RendererDebug};
|
||||
Setting<bool> disable_shader_loop_safety_checks{
|
||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
||||
Category::RendererDebug};
|
||||
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
||||
Category::RendererDebug};
|
||||
|
||||
// System
|
||||
SwitchableSetting<Language, true> language_index{linkage,
|
||||
Language::EnglishAmerican,
|
||||
Language::Japanese,
|
||||
Language::PortugueseBrazilian,
|
||||
"language_index",
|
||||
Category::System};
|
||||
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan,
|
||||
Region::Taiwan, "region_index", Category::System};
|
||||
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
||||
TimeZone::Auto, TimeZone::Zulu,
|
||||
"time_zone_index", Category::System};
|
||||
// Measured in seconds since epoch
|
||||
SwitchableSetting<bool> custom_rtc_enabled{
|
||||
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
||||
SwitchableSetting<s64> custom_rtc{
|
||||
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
||||
false, true, &custom_rtc_enabled};
|
||||
SwitchableSetting<s64, true> custom_rtc_offset{linkage,
|
||||
0,
|
||||
std::numeric_limits<int>::min(),
|
||||
std::numeric_limits<int>::max(),
|
||||
"custom_rtc_offset",
|
||||
Category::System,
|
||||
Specialization::Countable,
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<bool> rng_seed_enabled{
|
||||
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
|
||||
SwitchableSetting<u32> rng_seed{
|
||||
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
|
||||
true, true, &rng_seed_enabled};
|
||||
Setting<std::string> device_name{
|
||||
linkage, "yuzu", "device_name", Category::System, Specialization::Default, true, true};
|
||||
|
||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||
|
||||
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
||||
#ifdef ANDROID
|
||||
ConsoleMode::Handheld,
|
||||
#else
|
||||
ConsoleMode::Docked,
|
||||
#endif
|
||||
"use_docked_mode",
|
||||
Category::System,
|
||||
Specialization::Radio,
|
||||
true,
|
||||
true};
|
||||
|
||||
// Linux
|
||||
SwitchableSetting<bool> enable_gamemode{linkage, true, "enable_gamemode", Category::Linux};
|
||||
|
||||
// Controls
|
||||
InputSetting<std::array<PlayerInput, 10>> players;
|
||||
|
||||
Setting<bool> enable_raw_input{
|
||||
linkage, false, "enable_raw_input", Category::Controls, Specialization::Default,
|
||||
// Only read/write enable_raw_input on Windows platforms
|
||||
#ifdef _WIN32
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
};
|
||||
Setting<bool> controller_navigation{linkage, true, "controller_navigation", Category::Controls};
|
||||
Setting<bool> enable_joycon_driver{linkage, true, "enable_joycon_driver", Category::Controls};
|
||||
Setting<bool> enable_procon_driver{linkage, false, "enable_procon_driver", Category::Controls};
|
||||
|
||||
SwitchableSetting<bool> vibration_enabled{linkage, true, "vibration_enabled",
|
||||
Category::Controls};
|
||||
SwitchableSetting<bool> enable_accurate_vibrations{linkage, false, "enable_accurate_vibrations",
|
||||
Category::Controls};
|
||||
|
||||
SwitchableSetting<bool> motion_enabled{linkage, true, "motion_enabled", Category::Controls};
|
||||
Setting<std::string> udp_input_servers{linkage, "127.0.0.1:26760", "udp_input_servers",
|
||||
Category::Controls};
|
||||
Setting<bool> enable_udp_controller{linkage, false, "enable_udp_controller",
|
||||
Category::Controls};
|
||||
|
||||
Setting<bool> pause_tas_on_load{linkage, true, "pause_tas_on_load", Category::Controls};
|
||||
Setting<bool> tas_enable{linkage, false, "tas_enable", Category::Controls};
|
||||
Setting<bool> tas_loop{linkage, false, "tas_loop", Category::Controls};
|
||||
|
||||
Setting<bool> mouse_panning{
|
||||
linkage, false, "mouse_panning", Category::Controls, Specialization::Default, false};
|
||||
Setting<u8, true> mouse_panning_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_sensitivity", Category::Controls};
|
||||
Setting<bool> mouse_enabled{linkage, false, "mouse_enabled", Category::Controls};
|
||||
|
||||
Setting<u8, true> mouse_panning_x_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_x_sensitivity", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_y_sensitivity{
|
||||
linkage, 50, 1, 100, "mouse_panning_y_sensitivity", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_deadzone_counterweight{
|
||||
linkage, 20, 0, 100, "mouse_panning_deadzone_counterweight", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_decay_strength{
|
||||
linkage, 18, 0, 100, "mouse_panning_decay_strength", Category::Controls};
|
||||
Setting<u8, true> mouse_panning_min_decay{
|
||||
linkage, 6, 0, 100, "mouse_panning_min_decay", Category::Controls};
|
||||
|
||||
Setting<bool> emulate_analog_keyboard{linkage, false, "emulate_analog_keyboard",
|
||||
Category::Controls};
|
||||
Setting<bool> keyboard_enabled{linkage, false, "keyboard_enabled", Category::Controls};
|
||||
|
||||
Setting<bool> debug_pad_enabled{linkage, false, "debug_pad_enabled", Category::Controls};
|
||||
ButtonsRaw debug_pad_buttons;
|
||||
AnalogsRaw debug_pad_analogs;
|
||||
|
||||
TouchscreenInput touchscreen;
|
||||
|
||||
Setting<std::string> touch_device{linkage, "min_x:100,min_y:50,max_x:1800,max_y:850",
|
||||
"touch_device", Category::Controls};
|
||||
Setting<int> touch_from_button_map_index{linkage, 0, "touch_from_button_map",
|
||||
Category::Controls};
|
||||
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
||||
|
||||
Setting<bool> enable_ring_controller{linkage, true, "enable_ring_controller",
|
||||
Category::Controls};
|
||||
RingconRaw ringcon_analogs;
|
||||
|
||||
Setting<bool> enable_ir_sensor{linkage, false, "enable_ir_sensor", Category::Controls};
|
||||
Setting<std::string> ir_sensor_device{linkage, "auto", "ir_sensor_device", Category::Controls};
|
||||
|
||||
Setting<bool> random_amiibo_id{linkage, false, "random_amiibo_id", Category::Controls};
|
||||
|
||||
// Data Storage
|
||||
Setting<bool> use_virtual_sd{linkage, true, "use_virtual_sd", Category::DataStorage};
|
||||
Setting<bool> gamecard_inserted{linkage, false, "gamecard_inserted", Category::DataStorage};
|
||||
Setting<bool> gamecard_current_game{linkage, false, "gamecard_current_game",
|
||||
Category::DataStorage};
|
||||
Setting<std::string> gamecard_path{linkage, std::string(), "gamecard_path",
|
||||
Category::DataStorage};
|
||||
|
||||
// Debugging
|
||||
bool record_frame_times;
|
||||
Setting<bool> use_gdbstub{linkage, false, "use_gdbstub", Category::Debugging};
|
||||
Setting<u16> gdbstub_port{linkage, 6543, "gdbstub_port", Category::Debugging};
|
||||
Setting<std::string> program_args{linkage, std::string(), "program_args", Category::Debugging};
|
||||
Setting<bool> dump_exefs{linkage, false, "dump_exefs", Category::Debugging};
|
||||
Setting<bool> dump_nso{linkage, false, "dump_nso", Category::Debugging};
|
||||
Setting<bool> dump_shaders{
|
||||
linkage, false, "dump_shaders", Category::DebuggingGraphics, Specialization::Default,
|
||||
false};
|
||||
Setting<bool> dump_macros{
|
||||
linkage, false, "dump_macros", Category::DebuggingGraphics, Specialization::Default, false};
|
||||
Setting<bool> enable_fs_access_log{linkage, false, "enable_fs_access_log", Category::Debugging};
|
||||
Setting<bool> reporting_services{
|
||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> extended_logging{
|
||||
linkage, false, "extended_logging", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> use_debug_asserts{linkage, false, "use_debug_asserts", Category::Debugging};
|
||||
Setting<bool> use_auto_stub{
|
||||
linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
|
||||
Category::Debugging};
|
||||
Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
|
||||
|
||||
// Miscellaneous
|
||||
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
|
||||
|
||||
// Network
|
||||
Setting<std::string> network_interface{linkage, std::string(), "network_interface",
|
||||
Category::Network};
|
||||
|
||||
// WebService
|
||||
Setting<bool> enable_telemetry{linkage, true, "enable_telemetry", Category::WebService};
|
||||
Setting<std::string> web_api_url{linkage, "https://api.yuzu-emu.org", "web_api_url",
|
||||
Category::WebService};
|
||||
Setting<std::string> yuzu_username{linkage, std::string(), "yuzu_username",
|
||||
Category::WebService};
|
||||
Setting<std::string> yuzu_token{linkage, std::string(), "yuzu_token", Category::WebService};
|
||||
|
||||
// Add-Ons
|
||||
std::map<u64, std::vector<std::string>> disabled_addons;
|
||||
};
|
||||
|
||||
extern Values values;
|
||||
|
||||
void UpdateGPUAccuracy();
|
||||
bool IsGPULevelExtreme();
|
||||
bool IsGPULevelHigh();
|
||||
|
||||
bool IsFastmemEnabled();
|
||||
void SetNceEnabled(bool is_64bit);
|
||||
bool IsNceEnabled();
|
||||
|
||||
bool IsDockedMode();
|
||||
|
||||
float Volume();
|
||||
|
||||
std::string GetTimeZoneString(TimeZone time_zone);
|
||||
|
||||
void LogSettings();
|
||||
|
||||
void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info);
|
||||
void UpdateRescalingInfo();
|
||||
|
||||
// Restore the global state of all applicable settings in the Values struct
|
||||
void RestoreGlobalState(bool is_powered_on);
|
||||
|
||||
bool IsConfiguringGlobal();
|
||||
void SetConfiguringGlobal(bool is_global);
|
||||
|
||||
} // namespace Settings
|
||||
274
common/settings_common.h
Executable file
274
common/settings_common.h
Executable file
|
|
@ -0,0 +1,274 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include "common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
enum class Category : u32 {
|
||||
Android,
|
||||
Audio,
|
||||
Core,
|
||||
Cpu,
|
||||
CpuDebug,
|
||||
CpuUnsafe,
|
||||
Overlay,
|
||||
Renderer,
|
||||
RendererAdvanced,
|
||||
RendererDebug,
|
||||
System,
|
||||
SystemAudio,
|
||||
DataStorage,
|
||||
Debugging,
|
||||
DebuggingGraphics,
|
||||
GpuDriver,
|
||||
Miscellaneous,
|
||||
Network,
|
||||
WebService,
|
||||
AddOns,
|
||||
Controls,
|
||||
Ui,
|
||||
UiAudio,
|
||||
UiGeneral,
|
||||
UiLayout,
|
||||
UiGameList,
|
||||
Screenshots,
|
||||
Shortcuts,
|
||||
Multiplayer,
|
||||
Services,
|
||||
Paths,
|
||||
Linux,
|
||||
LibraryApplet,
|
||||
MaxEnum,
|
||||
};
|
||||
|
||||
constexpr u8 SpecializationTypeMask = 0xf;
|
||||
constexpr u8 SpecializationAttributeMask = 0xf0;
|
||||
constexpr u8 SpecializationAttributeOffset = 4;
|
||||
|
||||
// Scalar and countable could have better names
|
||||
enum Specialization : u8 {
|
||||
Default = 0,
|
||||
Time = 1, // Duration or specific moment in time
|
||||
Hex = 2, // Hexadecimal number
|
||||
List = 3, // Setting has specific members
|
||||
RuntimeList = 4, // Members of the list are determined during runtime
|
||||
Scalar = 5, // Values are continuous
|
||||
Countable = 6, // Can be stepped through
|
||||
Paired = 7, // Another setting is associated with this setting
|
||||
Radio = 8, // Setting should be presented in a radio group
|
||||
|
||||
Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage
|
||||
};
|
||||
|
||||
class BasicSetting;
|
||||
|
||||
class Linkage {
|
||||
public:
|
||||
explicit Linkage(u32 initial_count = 0);
|
||||
~Linkage();
|
||||
std::map<Category, std::vector<BasicSetting*>> by_category{};
|
||||
std::map<std::string, Settings::BasicSetting*> by_key{};
|
||||
std::vector<std::function<void()>> restore_functions{};
|
||||
u32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicSetting is an abstract class that only keeps track of metadata. The string methods are
|
||||
* available to get data values out.
|
||||
*/
|
||||
class BasicSetting {
|
||||
protected:
|
||||
explicit BasicSetting(Linkage& linkage, const std::string& name, Category category_, bool save_,
|
||||
bool runtime_modifiable_, u32 specialization,
|
||||
BasicSetting* other_setting);
|
||||
|
||||
public:
|
||||
virtual ~BasicSetting();
|
||||
|
||||
/*
|
||||
* Data retrieval
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a string representation of the internal data. If the Setting is Switchable, it
|
||||
* respects the internal global state: it is based on GetValue().
|
||||
*
|
||||
* @returns A string representation of the internal data.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string ToString() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the global version of internal data. If the Setting is
|
||||
* not Switchable, it behaves like ToString.
|
||||
*
|
||||
* @returns A string representation of the global version of internal data.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string ToStringGlobal() const;
|
||||
|
||||
/**
|
||||
* @returns A string representation of the Setting's default value.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string DefaultToString() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the minimum value of the setting. If the Setting is not
|
||||
* ranged, the string represents the default initialization of the data type.
|
||||
*
|
||||
* @returns A string representation of the minimum value of the setting.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string MinVal() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the maximum value of the setting. If the Setting is not
|
||||
* ranged, the string represents the default initialization of the data type.
|
||||
*
|
||||
* @returns A string representation of the maximum value of the setting.
|
||||
*/
|
||||
[[nodiscard]] virtual std::string MaxVal() const = 0;
|
||||
|
||||
/**
|
||||
* Takes a string input, converts it to the internal data type if necessary, and then runs
|
||||
* SetValue with it.
|
||||
*
|
||||
* @param load String of the input data.
|
||||
*/
|
||||
virtual void LoadString(const std::string& load) = 0;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the data. If the data is an enum, it returns a string of
|
||||
* the enum value. If the internal data type is not an enum, this is equivalent to ToString.
|
||||
*
|
||||
* e.g. renderer_backend.Canonicalize() == "OpenGL"
|
||||
*
|
||||
* @returns Canonicalized string representation of the internal data
|
||||
*/
|
||||
[[nodiscard]] virtual std::string Canonicalize() const = 0;
|
||||
|
||||
/*
|
||||
* Metadata
|
||||
*/
|
||||
|
||||
/**
|
||||
* @returns A unique identifier for the Setting's internal data type.
|
||||
*/
|
||||
[[nodiscard]] virtual std::type_index TypeId() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the Setting's internal data type is an enum.
|
||||
*
|
||||
* @returns True if the Setting's internal data type is an enum
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool IsEnum() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the current setting is Switchable.
|
||||
*
|
||||
* @returns If the setting is a SwitchableSetting
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool Switchable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to suggest that a frontend can read or write the setting to a configuration
|
||||
* file.
|
||||
*
|
||||
* @returns The save preference
|
||||
*/
|
||||
[[nodiscard]] bool Save() const;
|
||||
|
||||
/**
|
||||
* @returns true if the current setting can be changed while the guest is running.
|
||||
*/
|
||||
[[nodiscard]] bool RuntimeModifiable() const;
|
||||
|
||||
/**
|
||||
* @returns A unique number corresponding to the setting.
|
||||
*/
|
||||
[[nodiscard]] constexpr u32 Id() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setting's category AKA INI group.
|
||||
*
|
||||
* @returns The setting's category
|
||||
*/
|
||||
[[nodiscard]] Category GetCategory() const;
|
||||
|
||||
/**
|
||||
* @returns Extra metadata for data representation in frontend implementations.
|
||||
*/
|
||||
[[nodiscard]] u32 Specialization() const;
|
||||
|
||||
/**
|
||||
* @returns Another BasicSetting if one is paired, or nullptr otherwise.
|
||||
*/
|
||||
[[nodiscard]] BasicSetting* PairedSetting() const;
|
||||
|
||||
/**
|
||||
* Returns the label this setting was created with.
|
||||
*
|
||||
* @returns A reference to the label
|
||||
*/
|
||||
[[nodiscard]] const std::string& GetLabel() const;
|
||||
|
||||
/**
|
||||
* @returns If the Setting checks input values for valid ranges.
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool Ranged() const = 0;
|
||||
|
||||
/**
|
||||
* @returns The index of the enum if the underlying setting type is an enum, else max of u32.
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr u32 EnumIndex() const = 0;
|
||||
|
||||
/**
|
||||
* @returns True if the underlying type is a floating point storage
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool IsFloatingPoint() const = 0;
|
||||
|
||||
/**
|
||||
* @returns True if the underlying type is an integer storage
|
||||
*/
|
||||
[[nodiscard]] virtual constexpr bool IsIntegral() const = 0;
|
||||
|
||||
/*
|
||||
* Switchable settings
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets a setting's global state. True means use the normal setting, false to use a custom
|
||||
* value. Has no effect if the Setting is not Switchable.
|
||||
*
|
||||
* @param global The desired state
|
||||
*/
|
||||
virtual void SetGlobal(bool global);
|
||||
|
||||
/**
|
||||
* Returns true if the setting is using the normal setting value. Always true if the setting is
|
||||
* not Switchable.
|
||||
*
|
||||
* @returns The Setting's global state
|
||||
*/
|
||||
[[nodiscard]] virtual bool UsingGlobal() const;
|
||||
|
||||
private:
|
||||
const std::string label; ///< The setting's label
|
||||
const Category category; ///< The setting's category AKA INI group
|
||||
const u32 id; ///< Unique integer for the setting
|
||||
const bool save; ///< Suggests if the setting should be saved and read to a frontend config
|
||||
const bool
|
||||
runtime_modifiable; ///< Suggests if the setting can be modified while a guest is running
|
||||
const u32 specialization; ///< Extra data to identify representation of a setting
|
||||
BasicSetting* const other_setting; ///< A paired setting
|
||||
};
|
||||
|
||||
} // namespace Settings
|
||||
223
common/settings_enums.h
Executable file
223
common/settings_enums.h
Executable file
|
|
@ -0,0 +1,223 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
template <typename T>
|
||||
struct EnumMetadata {
|
||||
static std::vector<std::pair<std::string, T>> Canonicalizations();
|
||||
static u32 Index();
|
||||
};
|
||||
|
||||
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
|
||||
#define PAIR_44(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_45(N, __VA_ARGS__))
|
||||
#define PAIR_43(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_44(N, __VA_ARGS__))
|
||||
#define PAIR_42(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_43(N, __VA_ARGS__))
|
||||
#define PAIR_41(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_42(N, __VA_ARGS__))
|
||||
#define PAIR_40(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_41(N, __VA_ARGS__))
|
||||
#define PAIR_39(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_40(N, __VA_ARGS__))
|
||||
#define PAIR_38(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_39(N, __VA_ARGS__))
|
||||
#define PAIR_37(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_38(N, __VA_ARGS__))
|
||||
#define PAIR_36(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_37(N, __VA_ARGS__))
|
||||
#define PAIR_35(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_36(N, __VA_ARGS__))
|
||||
#define PAIR_34(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_35(N, __VA_ARGS__))
|
||||
#define PAIR_33(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_34(N, __VA_ARGS__))
|
||||
#define PAIR_32(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_33(N, __VA_ARGS__))
|
||||
#define PAIR_31(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_32(N, __VA_ARGS__))
|
||||
#define PAIR_30(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_31(N, __VA_ARGS__))
|
||||
#define PAIR_29(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_30(N, __VA_ARGS__))
|
||||
#define PAIR_28(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_29(N, __VA_ARGS__))
|
||||
#define PAIR_27(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_28(N, __VA_ARGS__))
|
||||
#define PAIR_26(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_27(N, __VA_ARGS__))
|
||||
#define PAIR_25(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_26(N, __VA_ARGS__))
|
||||
#define PAIR_24(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_25(N, __VA_ARGS__))
|
||||
#define PAIR_23(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_24(N, __VA_ARGS__))
|
||||
#define PAIR_22(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_23(N, __VA_ARGS__))
|
||||
#define PAIR_21(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_22(N, __VA_ARGS__))
|
||||
#define PAIR_20(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_21(N, __VA_ARGS__))
|
||||
#define PAIR_19(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_20(N, __VA_ARGS__))
|
||||
#define PAIR_18(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_19(N, __VA_ARGS__))
|
||||
#define PAIR_17(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_18(N, __VA_ARGS__))
|
||||
#define PAIR_16(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_17(N, __VA_ARGS__))
|
||||
#define PAIR_15(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_16(N, __VA_ARGS__))
|
||||
#define PAIR_14(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_15(N, __VA_ARGS__))
|
||||
#define PAIR_13(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_14(N, __VA_ARGS__))
|
||||
#define PAIR_12(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_13(N, __VA_ARGS__))
|
||||
#define PAIR_11(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_12(N, __VA_ARGS__))
|
||||
#define PAIR_10(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_11(N, __VA_ARGS__))
|
||||
#define PAIR_9(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_10(N, __VA_ARGS__))
|
||||
#define PAIR_8(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_9(N, __VA_ARGS__))
|
||||
#define PAIR_7(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_8(N, __VA_ARGS__))
|
||||
#define PAIR_6(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_7(N, __VA_ARGS__))
|
||||
#define PAIR_5(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_6(N, __VA_ARGS__))
|
||||
#define PAIR_4(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_5(N, __VA_ARGS__))
|
||||
#define PAIR_3(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_4(N, __VA_ARGS__))
|
||||
#define PAIR_2(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_3(N, __VA_ARGS__))
|
||||
#define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__))
|
||||
#define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__))
|
||||
|
||||
#define ENUM(NAME, ...) \
|
||||
enum class NAME : u32 { __VA_ARGS__ }; \
|
||||
template <> \
|
||||
inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
|
||||
return {PAIR(NAME, __VA_ARGS__)}; \
|
||||
} \
|
||||
template <> \
|
||||
inline u32 EnumMetadata<NAME>::Index() { \
|
||||
return __COUNTER__; \
|
||||
}
|
||||
|
||||
// AudioEngine must be specified discretely due to having existing but slightly different
|
||||
// canonicalizations
|
||||
// TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id
|
||||
enum class AudioEngine : u32 {
|
||||
Auto,
|
||||
Cubeb,
|
||||
Sdl2,
|
||||
Null,
|
||||
Oboe,
|
||||
};
|
||||
|
||||
template <>
|
||||
inline std::vector<std::pair<std::string, AudioEngine>>
|
||||
EnumMetadata<AudioEngine>::Canonicalizations() {
|
||||
return {
|
||||
{"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2},
|
||||
{"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe},
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
inline u32 EnumMetadata<AudioEngine>::Index() {
|
||||
// This is just a sufficiently large number that is more than the number of other enums declared
|
||||
// here
|
||||
return 100;
|
||||
}
|
||||
|
||||
ENUM(AudioMode, Mono, Stereo, Surround);
|
||||
|
||||
ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch,
|
||||
Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin,
|
||||
ChineseSimplified, ChineseTraditional, PortugueseBrazilian);
|
||||
|
||||
ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan);
|
||||
|
||||
ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt,
|
||||
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
||||
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
||||
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
||||
|
||||
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
|
||||
|
||||
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
||||
|
||||
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
||||
|
||||
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
||||
|
||||
ENUM(VramUsageMode, Conservative, Aggressive);
|
||||
|
||||
ENUM(RendererBackend, OpenGL, Vulkan, Null);
|
||||
|
||||
ENUM(ShaderBackend, Glsl, Glasm, SpirV);
|
||||
|
||||
ENUM(GpuAccuracy, Normal, High, Extreme);
|
||||
|
||||
ENUM(CpuBackend, Dynarmic, Nce);
|
||||
|
||||
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
|
||||
|
||||
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb);
|
||||
|
||||
ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);
|
||||
|
||||
ENUM(FullscreenMode, Borderless, Exclusive);
|
||||
|
||||
ENUM(NvdecEmulation, Off, Cpu, Gpu);
|
||||
|
||||
ENUM(ResolutionSetup, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X,
|
||||
Res8X);
|
||||
|
||||
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, ScaleForce, Fsr, MaxEnum);
|
||||
|
||||
ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
|
||||
|
||||
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
|
||||
|
||||
ENUM(ConsoleMode, Handheld, Docked);
|
||||
|
||||
ENUM(AppletMode, HLE, LLE);
|
||||
|
||||
template <typename Type>
|
||||
inline std::string CanonicalizeEnum(Type id) {
|
||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||
for (auto& [name, value] : group) {
|
||||
if (value == id) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type ToEnum(const std::string& canonicalization) {
|
||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||
for (auto& [name, value] : group) {
|
||||
if (name == canonicalization) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} // namespace Settings
|
||||
|
||||
#undef ENUM
|
||||
#undef PAIR
|
||||
#undef PAIR_1
|
||||
#undef PAIR_2
|
||||
#undef PAIR_3
|
||||
#undef PAIR_4
|
||||
#undef PAIR_5
|
||||
#undef PAIR_6
|
||||
#undef PAIR_7
|
||||
#undef PAIR_8
|
||||
#undef PAIR_9
|
||||
#undef PAIR_10
|
||||
#undef PAIR_12
|
||||
#undef PAIR_13
|
||||
#undef PAIR_14
|
||||
#undef PAIR_15
|
||||
#undef PAIR_16
|
||||
#undef PAIR_17
|
||||
#undef PAIR_18
|
||||
#undef PAIR_19
|
||||
#undef PAIR_20
|
||||
#undef PAIR_22
|
||||
#undef PAIR_23
|
||||
#undef PAIR_24
|
||||
#undef PAIR_25
|
||||
#undef PAIR_26
|
||||
#undef PAIR_27
|
||||
#undef PAIR_28
|
||||
#undef PAIR_29
|
||||
#undef PAIR_30
|
||||
#undef PAIR_32
|
||||
#undef PAIR_33
|
||||
#undef PAIR_34
|
||||
#undef PAIR_35
|
||||
#undef PAIR_36
|
||||
#undef PAIR_37
|
||||
#undef PAIR_38
|
||||
#undef PAIR_39
|
||||
#undef PAIR_40
|
||||
#undef PAIR_42
|
||||
#undef PAIR_43
|
||||
#undef PAIR_44
|
||||
#undef PAIR_45
|
||||
413
common/settings_input.h
Executable file
413
common/settings_input.h
Executable file
|
|
@ -0,0 +1,413 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
#include "common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace NativeButton {
|
||||
enum Values : int {
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
LStick,
|
||||
RStick,
|
||||
L,
|
||||
R,
|
||||
ZL,
|
||||
ZR,
|
||||
Plus,
|
||||
Minus,
|
||||
|
||||
DLeft,
|
||||
DUp,
|
||||
DRight,
|
||||
DDown,
|
||||
|
||||
SLLeft,
|
||||
SRLeft,
|
||||
|
||||
Home,
|
||||
Screenshot,
|
||||
|
||||
SLRight,
|
||||
SRRight,
|
||||
|
||||
NumButtons,
|
||||
};
|
||||
|
||||
constexpr int BUTTON_HID_BEGIN = A;
|
||||
constexpr int BUTTON_NS_BEGIN = Home;
|
||||
|
||||
constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
|
||||
constexpr int BUTTON_NS_END = NumButtons;
|
||||
|
||||
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
|
||||
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
|
||||
|
||||
extern const std::array<const char*, NumButtons> mapping;
|
||||
|
||||
} // namespace NativeButton
|
||||
|
||||
namespace NativeAnalog {
|
||||
enum Values : int {
|
||||
LStick,
|
||||
RStick,
|
||||
|
||||
NumAnalogs,
|
||||
};
|
||||
|
||||
constexpr int STICK_HID_BEGIN = LStick;
|
||||
constexpr int STICK_HID_END = NumAnalogs;
|
||||
|
||||
extern const std::array<const char*, NumAnalogs> mapping;
|
||||
} // namespace NativeAnalog
|
||||
|
||||
namespace NativeTrigger {
|
||||
enum Values : int {
|
||||
LTrigger,
|
||||
RTrigger,
|
||||
|
||||
NumTriggers,
|
||||
};
|
||||
|
||||
constexpr int TRIGGER_HID_BEGIN = LTrigger;
|
||||
constexpr int TRIGGER_HID_END = NumTriggers;
|
||||
} // namespace NativeTrigger
|
||||
|
||||
namespace NativeVibration {
|
||||
enum Values : int {
|
||||
LeftVibrationDevice,
|
||||
RightVibrationDevice,
|
||||
|
||||
NumVibrations,
|
||||
};
|
||||
|
||||
constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
|
||||
constexpr int VIBRATION_HID_END = NumVibrations;
|
||||
constexpr int NUM_VIBRATIONS_HID = NumVibrations;
|
||||
|
||||
extern const std::array<const char*, NumVibrations> mapping;
|
||||
}; // namespace NativeVibration
|
||||
|
||||
namespace NativeMotion {
|
||||
enum Values : int {
|
||||
MotionLeft,
|
||||
MotionRight,
|
||||
|
||||
NumMotions,
|
||||
};
|
||||
|
||||
constexpr int MOTION_HID_BEGIN = MotionLeft;
|
||||
constexpr int MOTION_HID_END = NumMotions;
|
||||
constexpr int NUM_MOTIONS_HID = NumMotions;
|
||||
|
||||
extern const std::array<const char*, NumMotions> mapping;
|
||||
} // namespace NativeMotion
|
||||
|
||||
namespace NativeMouseButton {
|
||||
enum Values {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Forward,
|
||||
Back,
|
||||
|
||||
NumMouseButtons,
|
||||
};
|
||||
|
||||
constexpr int MOUSE_HID_BEGIN = Left;
|
||||
constexpr int MOUSE_HID_END = NumMouseButtons;
|
||||
constexpr int NUM_MOUSE_HID = NumMouseButtons;
|
||||
|
||||
extern const std::array<const char*, NumMouseButtons> mapping;
|
||||
} // namespace NativeMouseButton
|
||||
|
||||
namespace NativeMouseWheel {
|
||||
enum Values {
|
||||
X,
|
||||
Y,
|
||||
|
||||
NumMouseWheels,
|
||||
};
|
||||
|
||||
extern const std::array<const char*, NumMouseWheels> mapping;
|
||||
} // namespace NativeMouseWheel
|
||||
|
||||
namespace NativeKeyboard {
|
||||
enum Keys {
|
||||
None,
|
||||
|
||||
A = 4,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
N1,
|
||||
N2,
|
||||
N3,
|
||||
N4,
|
||||
N5,
|
||||
N6,
|
||||
N7,
|
||||
N8,
|
||||
N9,
|
||||
N0,
|
||||
Return,
|
||||
Escape,
|
||||
Backspace,
|
||||
Tab,
|
||||
Space,
|
||||
Minus,
|
||||
Plus,
|
||||
OpenBracket,
|
||||
CloseBracket,
|
||||
Pipe,
|
||||
Tilde,
|
||||
Semicolon,
|
||||
Quote,
|
||||
Backquote,
|
||||
Comma,
|
||||
Period,
|
||||
Slash,
|
||||
CapsLockKey,
|
||||
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
PrintScreen,
|
||||
ScrollLockKey,
|
||||
Pause,
|
||||
Insert,
|
||||
Home,
|
||||
PageUp,
|
||||
Delete,
|
||||
End,
|
||||
PageDown,
|
||||
Right,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
|
||||
NumLockKey,
|
||||
KPSlash,
|
||||
KPAsterisk,
|
||||
KPMinus,
|
||||
KPPlus,
|
||||
KPEnter,
|
||||
KP1,
|
||||
KP2,
|
||||
KP3,
|
||||
KP4,
|
||||
KP5,
|
||||
KP6,
|
||||
KP7,
|
||||
KP8,
|
||||
KP9,
|
||||
KP0,
|
||||
KPDot,
|
||||
|
||||
Key102,
|
||||
Compose,
|
||||
Power,
|
||||
KPEqual,
|
||||
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
F21,
|
||||
F22,
|
||||
F23,
|
||||
F24,
|
||||
|
||||
Open,
|
||||
Help,
|
||||
Properties,
|
||||
Front,
|
||||
Stop,
|
||||
Repeat,
|
||||
Undo,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Find,
|
||||
Mute,
|
||||
VolumeUp,
|
||||
VolumeDown,
|
||||
CapsLockActive,
|
||||
NumLockActive,
|
||||
ScrollLockActive,
|
||||
KPComma,
|
||||
|
||||
Ro = 0x87,
|
||||
KatakanaHiragana,
|
||||
Yen,
|
||||
Henkan,
|
||||
Muhenkan,
|
||||
NumPadCommaPc98,
|
||||
|
||||
HangulEnglish = 0x90,
|
||||
Hanja,
|
||||
KatakanaKey,
|
||||
HiraganaKey,
|
||||
ZenkakuHankaku,
|
||||
|
||||
LeftControlKey = 0xE0,
|
||||
LeftShiftKey,
|
||||
LeftAltKey,
|
||||
LeftMetaKey,
|
||||
RightControlKey,
|
||||
RightShiftKey,
|
||||
RightAltKey,
|
||||
RightMetaKey,
|
||||
|
||||
MediaPlayPause,
|
||||
MediaStopCD,
|
||||
MediaPrevious,
|
||||
MediaNext,
|
||||
MediaEject,
|
||||
MediaVolumeUp,
|
||||
MediaVolumeDown,
|
||||
MediaMute,
|
||||
MediaWebsite,
|
||||
MediaBack,
|
||||
MediaForward,
|
||||
MediaStop,
|
||||
MediaFind,
|
||||
MediaScrollUp,
|
||||
MediaScrollDown,
|
||||
MediaEdit,
|
||||
MediaSleep,
|
||||
MediaCoffee,
|
||||
MediaRefresh,
|
||||
MediaCalculator,
|
||||
|
||||
NumKeyboardKeys,
|
||||
};
|
||||
|
||||
static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
|
||||
|
||||
enum Modifiers {
|
||||
LeftControl,
|
||||
LeftShift,
|
||||
LeftAlt,
|
||||
LeftMeta,
|
||||
RightControl,
|
||||
RightShift,
|
||||
RightAlt,
|
||||
RightMeta,
|
||||
CapsLock,
|
||||
ScrollLock,
|
||||
NumLock,
|
||||
Katakana,
|
||||
Hiragana,
|
||||
|
||||
NumKeyboardMods,
|
||||
};
|
||||
|
||||
constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
|
||||
constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
|
||||
constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
|
||||
|
||||
constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
|
||||
constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
|
||||
constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
|
||||
|
||||
} // namespace NativeKeyboard
|
||||
|
||||
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
|
||||
using RingconRaw = std::string;
|
||||
|
||||
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
|
||||
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
|
||||
|
||||
enum class ControllerType {
|
||||
ProController,
|
||||
DualJoyconDetached,
|
||||
LeftJoycon,
|
||||
RightJoycon,
|
||||
Handheld,
|
||||
GameCube,
|
||||
Pokeball,
|
||||
NES,
|
||||
SNES,
|
||||
N64,
|
||||
SegaGenesis,
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
bool connected;
|
||||
ControllerType controller_type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
MotionsRaw motions;
|
||||
|
||||
bool vibration_enabled;
|
||||
int vibration_strength;
|
||||
|
||||
u32 body_color_left;
|
||||
u32 body_color_right;
|
||||
u32 button_color_left;
|
||||
u32 button_color_right;
|
||||
std::string profile_name;
|
||||
|
||||
// This is meant to tell the Android frontend whether to use a device's built-in vibration
|
||||
// motor or a controller's vibrations.
|
||||
bool use_system_vibrator;
|
||||
};
|
||||
|
||||
struct TouchscreenInput {
|
||||
bool enabled;
|
||||
std::string device;
|
||||
|
||||
u32 finger;
|
||||
u32 diameter_x;
|
||||
u32 diameter_y;
|
||||
u32 rotation_angle;
|
||||
};
|
||||
} // namespace Settings
|
||||
422
common/settings_setting.h
Executable file
422
common/settings_setting.h
Executable file
|
|
@ -0,0 +1,422 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <fmt/core.h>
|
||||
#include "common_types.h"
|
||||
#include "settings_common.h"
|
||||
#include "settings_enums.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
/** The Setting class is a simple resource manager. It defines a label and default value
|
||||
* alongside the actual value of the setting for simpler and less-error prone use with frontend
|
||||
* configurations. Specifying a default value and label is required. A minimum and maximum range
|
||||
* can be specified for sanitization.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class Setting : public BasicSetting {
|
||||
protected:
|
||||
Setting() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
explicit Setting(Linkage& linkage, const Type& default_val, const std::string& name,
|
||||
Category category_, u32 specialization_ = Specialization::Default,
|
||||
bool save_ = true, bool runtime_modifiable_ = false,
|
||||
BasicSetting* other_setting_ = nullptr)
|
||||
requires(!ranged)
|
||||
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_,
|
||||
other_setting_),
|
||||
value{default_val}, default_value{default_val} {}
|
||||
virtual ~Setting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
explicit Setting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
||||
const Type& max_val, const std::string& name, Category category_,
|
||||
u32 specialization_ = Specialization::Default, bool save_ = true,
|
||||
bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr)
|
||||
requires(ranged)
|
||||
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_,
|
||||
other_setting_),
|
||||
value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting's value.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
[[nodiscard]] virtual const Type& GetValue() const {
|
||||
return value;
|
||||
}
|
||||
[[nodiscard]] virtual const Type& GetValue(bool need_global) const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setting to the given value.
|
||||
*
|
||||
* @param val The desired value
|
||||
*/
|
||||
virtual void SetValue(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value that this setting was created with.
|
||||
*
|
||||
* @returns A reference to the default value
|
||||
*/
|
||||
[[nodiscard]] const Type& GetDefault() const {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsEnum() const override {
|
||||
return std::is_enum_v<Type>;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] std::string ToString(const Type& value_) const {
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
return value_;
|
||||
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
||||
return value_.has_value() ? std::to_string(*value_) : "none";
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
return value_ ? "true" : "false";
|
||||
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
|
||||
// Compatibility with old AudioEngine setting being a string
|
||||
return CanonicalizeEnum(value_);
|
||||
} else if constexpr (std::is_floating_point_v<Type>) {
|
||||
return fmt::format("{:f}", value_);
|
||||
} else if constexpr (std::is_enum_v<Type>) {
|
||||
return std::to_string(static_cast<u32>(value_));
|
||||
} else {
|
||||
return std::to_string(value_);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Converts the value of the setting to a std::string. Respects the global state if the setting
|
||||
* has one.
|
||||
*
|
||||
* @returns The current setting as a std::string
|
||||
*/
|
||||
[[nodiscard]] std::string ToString() const override {
|
||||
return ToString(this->GetValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value of the setting as a std::string.
|
||||
*
|
||||
* @returns The default value as a string.
|
||||
*/
|
||||
[[nodiscard]] std::string DefaultToString() const override {
|
||||
return ToString(default_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the setting.
|
||||
*
|
||||
* @param val The desired setting value
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
virtual const Type& operator=(const Type& val) {
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting.
|
||||
*
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
explicit virtual operator const Type&() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given value to the Setting's type of value. Uses SetValue to enter the setting,
|
||||
* thus respecting its constraints.
|
||||
*
|
||||
* @param input The desired value
|
||||
*/
|
||||
void LoadString(const std::string& input) override final {
|
||||
if (input.empty()) {
|
||||
this->SetValue(this->GetDefault());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
this->SetValue(input);
|
||||
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
||||
this->SetValue(static_cast<u32>(std::stoul(input)));
|
||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||
this->SetValue(input == "true");
|
||||
} else if constexpr (std::is_same_v<Type, float>) {
|
||||
this->SetValue(std::stof(input));
|
||||
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
|
||||
this->SetValue(ToEnum<AudioEngine>(input));
|
||||
} else {
|
||||
this->SetValue(static_cast<Type>(std::stoll(input)));
|
||||
}
|
||||
} catch (std::invalid_argument&) {
|
||||
this->SetValue(this->GetDefault());
|
||||
} catch (std::out_of_range&) {
|
||||
this->SetValue(this->GetDefault());
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string Canonicalize() const override final {
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
return CanonicalizeEnum(this->GetValue());
|
||||
} else {
|
||||
return ToString(this->GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives us another way to identify the setting without having to go through a string.
|
||||
*
|
||||
* @returns the type_index of the setting's type
|
||||
*/
|
||||
[[nodiscard]] std::type_index TypeId() const override final {
|
||||
return std::type_index(typeid(Type));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr u32 EnumIndex() const override final {
|
||||
if constexpr (std::is_enum_v<Type>) {
|
||||
return EnumMetadata<Type>::Index();
|
||||
} else {
|
||||
return std::numeric_limits<u32>::max();
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsFloatingPoint() const final {
|
||||
return std::is_floating_point_v<Type>;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsIntegral() const final {
|
||||
return std::is_integral_v<Type>;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string MinVal() const override final {
|
||||
if constexpr (std::is_arithmetic_v<Type> && !ranged) {
|
||||
return this->ToString(std::numeric_limits<Type>::min());
|
||||
} else {
|
||||
return this->ToString(minimum);
|
||||
}
|
||||
}
|
||||
[[nodiscard]] std::string MaxVal() const override final {
|
||||
if constexpr (std::is_arithmetic_v<Type> && !ranged) {
|
||||
return this->ToString(std::numeric_limits<Type>::max());
|
||||
} else {
|
||||
return this->ToString(maximum);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Ranged() const override {
|
||||
return ranged;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type value{}; ///< The setting
|
||||
const Type default_value{}; ///< The default value
|
||||
const Type maximum{}; ///< Maximum allowed value of the setting
|
||||
const Type minimum{}; ///< Minimum allowed value of the setting
|
||||
};
|
||||
|
||||
/**
|
||||
* The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a
|
||||
* custom setting to switch to when a guest application specifically requires it. The effect is that
|
||||
* other components of the emulator can access the setting's intended value without any need for the
|
||||
* component to ask whether the custom or global setting is needed at the moment.
|
||||
*
|
||||
* By default, the global setting is used.
|
||||
*/
|
||||
template <typename Type, bool ranged = false>
|
||||
class SwitchableSetting : virtual public Setting<Type, ranged> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
template <typename T = BasicSetting>
|
||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
|
||||
Category category_, u32 specialization_ = Specialization::Default,
|
||||
bool save_ = true, bool runtime_modifiable_ = false,
|
||||
typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr)
|
||||
: Setting<Type, false>{
|
||||
linkage, default_val, name, category_, specialization_,
|
||||
save_, runtime_modifiable_, other_setting_} {
|
||||
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
|
||||
}
|
||||
virtual ~SwitchableSetting() = default;
|
||||
|
||||
/**
|
||||
* Sets a default value, minimum value, maximum value, and label.
|
||||
*
|
||||
* @param linkage Setting registry
|
||||
* @param default_val Initial value of the setting, and default value of the setting
|
||||
* @param min_val Sets the minimum allowed value of the setting
|
||||
* @param max_val Sets the maximum allowed value of the setting
|
||||
* @param name Label for the setting
|
||||
* @param category_ Category of the setting AKA INI group
|
||||
* @param specialization_ Suggestion for how frontend implementations represent this in a config
|
||||
* @param save_ Suggests that this should or should not be saved to a frontend config file
|
||||
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
|
||||
* @param other_setting_ A second Setting to associate to this one in metadata
|
||||
*/
|
||||
template <typename T = BasicSetting>
|
||||
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
|
||||
const Type& max_val, const std::string& name, Category category_,
|
||||
u32 specialization_ = Specialization::Default, bool save_ = true,
|
||||
bool runtime_modifiable_ = false,
|
||||
typename std::enable_if<ranged, T*>::type other_setting_ = nullptr)
|
||||
: Setting<Type, true>{linkage, default_val, min_val,
|
||||
max_val, name, category_,
|
||||
specialization_, save_, runtime_modifiable_,
|
||||
other_setting_} {
|
||||
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells this setting to represent either the global or custom setting when other member
|
||||
* functions are used.
|
||||
*
|
||||
* @param to_global Whether to use the global or custom setting.
|
||||
*/
|
||||
void SetGlobal(bool to_global) override final {
|
||||
use_global = to_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this setting is using the global setting or not.
|
||||
*
|
||||
* @returns The global state
|
||||
*/
|
||||
[[nodiscard]] bool UsingGlobal() const override final {
|
||||
return use_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either the global or custom setting depending on the values of this setting's global
|
||||
* state or if the global value was specifically requested.
|
||||
*
|
||||
* @param need_global Request global value regardless of setting's state; defaults to false
|
||||
*
|
||||
* @returns The required value of the setting
|
||||
*/
|
||||
[[nodiscard]] const Type& GetValue() const override final {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
[[nodiscard]] const Type& GetValue(bool need_global) const override final {
|
||||
if (use_global || need_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*/
|
||||
void SetValue(const Type& val) override final {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
} else {
|
||||
std::swap(custom, temp);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool Switchable() const override final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string ToStringGlobal() const override final {
|
||||
return this->ToString(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the current setting value depending on the global state.
|
||||
*
|
||||
* @param val The new value
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
const Type& operator=(const Type& val) override final {
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
return this->value;
|
||||
}
|
||||
std::swap(custom, temp);
|
||||
return custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setting value depending on the global state.
|
||||
*
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
explicit operator const Type&() const override final {
|
||||
if (use_global) {
|
||||
return this->value;
|
||||
}
|
||||
return custom;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool use_global{true}; ///< The setting's global state
|
||||
Type custom{}; ///< The custom value of the setting
|
||||
};
|
||||
|
||||
} // namespace Settings
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "../common/common_types.h"
|
||||
#include "nca_metadata.h"
|
||||
#include "../core/fs/vfs/vfs.h"
|
||||
|
||||
namespace Core::Crypto {
|
||||
class KeyManager;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue