Rebase to master

This commit is contained in:
Ameer 2020-07-14 13:04:02 -04:00
commit 93fe982a0c
122 changed files with 3430 additions and 1490 deletions

View File

@ -118,8 +118,17 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
# Configure C++ standard
# ===========================
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# boost asio's concept usage doesn't play nicely with some compilers yet.
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
if (MSVC)
add_compile_options(/std:c++latest)
# cubeb and boost still make use of deprecated result_of.
add_definitions(-D_HAS_DEPRECATED_RESULT_OF)
else()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
# Output binaries to bin/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
@ -151,7 +160,7 @@ macro(yuzu_find_packages)
# Cmake Pkg Prefix Version Conan Pkg
"Boost 1.71 boost/1.72.0"
"Catch2 2.11 catch2/2.11.0"
"fmt 6.2 fmt/6.2.0"
"fmt 7.0 fmt/7.0.1"
# can't use until https://github.com/bincrafters/community/issues/1173
#"libzip 1.5 libzip/1.5.2@bincrafters/stable"
"lz4 1.8 lz4/1.9.2"
@ -211,7 +220,7 @@ if(ENABLE_QT)
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
endif()
find_package(Qt5 5.9 COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
find_package(Qt5 5.9 COMPONENTS Widgets ${QT_PREFIX_HINT})
if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
endif()
@ -287,7 +296,7 @@ if (CONAN_REQUIRED_LIBS)
if(ENABLE_QT)
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
find_package(Qt5 5.9 REQUIRED COMPONENTS Widgets OpenGL)
find_package(Qt5 5.9 REQUIRED COMPONENTS Widgets)
if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
endif()
@ -330,13 +339,16 @@ elseif(SDL2_FOUND)
endif()
# Ensure libusb is properly configured (based on dolphin libusb include)
find_package(LibUSB)
if(NOT APPLE)
include(FindPkgConfig)
find_package(LibUSB)
endif()
if (NOT LIBUSB_FOUND)
add_subdirectory(externals/libusb)
set(LIBUSB_INCLUDE_DIR "")
set(LIBUSB_LIBRARIES usb)
endif()
# Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

View File

@ -15,7 +15,6 @@ function(copy_yuzu_Qt5_deps target_dir)
icuuc*.dll
Qt5Core$<$<CONFIG:Debug>:d>.*
Qt5Gui$<$<CONFIG:Debug>:d>.*
Qt5OpenGL$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
)

View File

@ -2,7 +2,7 @@ yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.gg/XQV6dn9)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.com/invite/u77vRWY)
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
@ -16,7 +16,7 @@ yuzu is licensed under the GPLv2 (or any later version). Refer to the license.tx
Check out our [website](https://yuzu-emu.org/)!
For development discussion, please join us on [Discord](https://discord.gg/XQV6dn9).
For development discussion, please join us on [Discord](https://discord.com/invite/u77vRWY).
### Development

2
externals/dynarmic vendored

@ -1 +1 @@
Subproject commit 4f967387c07365b7ea35d2fa3e19b7df8872a09b
Subproject commit 82417da7803e2cf18efc28a1cd3f3d0a4b6045ae

View File

@ -193,7 +193,7 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const
const std::size_t samples_to_write = num_channels * num_frames;
std::size_t samples_written;
if (Settings::values.enable_audio_stretching) {
if (Settings::values.enable_audio_stretching.GetValue()) {
const std::vector<s16> in{impl->queue.Pop()};
const std::size_t num_in{in.size() / num_channels};
s16* const out{reinterpret_cast<s16*>(buffer)};

View File

@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
release_event = Core::Timing::CreateEvent(
name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(); });
name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(cycles_late); });
}
void Stream::Play() {
@ -66,15 +66,6 @@ s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const {
return ns.count();
}
s64 Stream::GetBufferReleaseNSHostTiming(const Buffer& buffer) const {
const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
/// DSP signals before playing the last sample, in HLE we emulate this in this way
s64 base_samples = std::max<s64>(static_cast<s64>(num_samples) - 1, 0);
const auto ns =
std::chrono::nanoseconds((static_cast<u64>(base_samples) * 1000000000ULL) / sample_rate);
return ns.count();
}
static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
const float volume{std::clamp(Settings::Volume() - (1.0f - game_volume), 0.0f, 1.0f)};
@ -89,7 +80,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
}
}
void Stream::PlayNextBuffer() {
void Stream::PlayNextBuffer(s64 cycles_late) {
if (!IsPlaying()) {
// Ensure we are in playing state before playing the next buffer
sink_stream.Flush();
@ -114,18 +105,17 @@ void Stream::PlayNextBuffer() {
sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
if (core_timing.IsHostTiming()) {
core_timing.ScheduleEvent(GetBufferReleaseNSHostTiming(*active_buffer), release_event, {});
} else {
core_timing.ScheduleEvent(GetBufferReleaseNS(*active_buffer), release_event, {});
}
core_timing.ScheduleEvent(
GetBufferReleaseNS(*active_buffer) -
(Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late),
release_event, {});
}
void Stream::ReleaseActiveBuffer() {
void Stream::ReleaseActiveBuffer(s64 cycles_late) {
ASSERT(active_buffer);
released_buffers.push(std::move(active_buffer));
release_callback();
PlayNextBuffer();
PlayNextBuffer(cycles_late);
}
bool Stream::QueueBuffer(BufferPtr&& buffer) {

View File

@ -90,10 +90,10 @@ public:
private:
/// Plays the next queued buffer in the audio stream, starting playback if necessary
void PlayNextBuffer();
void PlayNextBuffer(s64 cycles_late = 0);
/// Releases the actively playing buffer, signalling that it has been completed
void ReleaseActiveBuffer();
void ReleaseActiveBuffer(s64 cycles_late = 0);
/// Gets the number of core cycles when the specified buffer will be released
s64 GetBufferReleaseNS(const Buffer& buffer) const;

View File

@ -11,7 +11,9 @@ namespace Common {
template <typename T>
constexpr T AlignUp(T value, std::size_t size) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
return static_cast<T>(value + (size - value % size) % size);
auto mod{static_cast<T>(value % size)};
value -= mod;
return static_cast<T>(mod == T{0} ? value : value + size);
}
template <typename T>

View File

@ -142,10 +142,32 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
// Timing
config.wall_clock_cntpct = uses_wall_clock;
// Optimizations
if (Settings::values.disable_cpu_opt) {
config.enable_optimizations = false;
config.enable_fast_dispatch = false;
// Safe optimizations
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
if (!Settings::values.cpuopt_page_tables) {
config.page_table = nullptr;
}
if (!Settings::values.cpuopt_block_linking) {
config.optimizations &= ~Dynarmic::OptimizationFlag::BlockLinking;
}
if (!Settings::values.cpuopt_return_stack_buffer) {
config.optimizations &= ~Dynarmic::OptimizationFlag::ReturnStackBuffer;
}
if (!Settings::values.cpuopt_fast_dispatcher) {
config.optimizations &= ~Dynarmic::OptimizationFlag::FastDispatch;
}
if (!Settings::values.cpuopt_context_elimination) {
config.optimizations &= ~Dynarmic::OptimizationFlag::GetSetElimination;
}
if (!Settings::values.cpuopt_const_prop) {
config.optimizations &= ~Dynarmic::OptimizationFlag::ConstProp;
}
if (!Settings::values.cpuopt_misc_ir) {
config.optimizations &= ~Dynarmic::OptimizationFlag::MiscIROpt;
}
if (!Settings::values.cpuopt_reduce_misalign_checks) {
config.only_detect_misalignment_via_page_table_on_page_boundary = false;
}
}
return std::make_unique<Dynarmic::A32::Jit>(config);

View File

@ -191,15 +191,37 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
// Unpredictable instructions
config.define_unpredictable_behaviour = true;
// Optimizations
if (Settings::values.disable_cpu_opt) {
config.enable_optimizations = false;
config.enable_fast_dispatch = false;
}
// Timing
config.wall_clock_cntpct = uses_wall_clock;
// Safe optimizations
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
if (!Settings::values.cpuopt_page_tables) {
config.page_table = nullptr;
}
if (!Settings::values.cpuopt_block_linking) {
config.optimizations &= ~Dynarmic::OptimizationFlag::BlockLinking;
}
if (!Settings::values.cpuopt_return_stack_buffer) {
config.optimizations &= ~Dynarmic::OptimizationFlag::ReturnStackBuffer;
}
if (!Settings::values.cpuopt_fast_dispatcher) {
config.optimizations &= ~Dynarmic::OptimizationFlag::FastDispatch;
}
if (!Settings::values.cpuopt_context_elimination) {
config.optimizations &= ~Dynarmic::OptimizationFlag::GetSetElimination;
}
if (!Settings::values.cpuopt_const_prop) {
config.optimizations &= ~Dynarmic::OptimizationFlag::ConstProp;
}
if (!Settings::values.cpuopt_misc_ir) {
config.optimizations &= ~Dynarmic::OptimizationFlag::MiscIROpt;
}
if (!Settings::values.cpuopt_reduce_misalign_checks) {
config.only_detect_misalignment_via_page_table_on_page_boundary = false;
}
}
return std::make_shared<Dynarmic::A64::Jit>(config);
}

View File

@ -147,8 +147,8 @@ struct System::Impl {
device_memory = std::make_unique<Core::DeviceMemory>(system);
is_multicore = Settings::values.use_multi_core;
is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation;
is_multicore = Settings::values.use_multi_core.GetValue();
is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation.GetValue();
kernel.SetMulticore(is_multicore);
cpu_manager.SetMulticore(is_multicore);
@ -162,7 +162,7 @@ struct System::Impl {
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch());
Settings::values.custom_rtc_differential =
Settings::values.custom_rtc.value_or(current_time) - current_time;
Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time;
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr)

View File

@ -172,7 +172,7 @@ void CoreTiming::ClearPendingEvents() {
}
void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
basic_lock.lock();
std::scoped_lock lock{basic_lock};
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
return e.type.lock().get() == event_type.get();
@ -183,12 +183,10 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
event_queue.erase(itr, event_queue.end());
std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
basic_lock.unlock();
}
std::optional<s64> CoreTiming::Advance() {
std::scoped_lock advance_scope{advance_lock};
std::scoped_lock basic_scope{basic_lock};
std::scoped_lock lock{advance_lock, basic_lock};
global_timer = GetGlobalTimeNs().count();
while (!event_queue.empty() && event_queue.front().time <= global_timer) {

View File

@ -695,8 +695,9 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
}
void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
if (s128_keys.find({id, field1, field2}) != s128_keys.end())
if (s128_keys.find({id, field1, field2}) != s128_keys.end() || key == Key128{}) {
return;
}
if (id == S128KeyType::Titlekey) {
Key128 rights_id;
std::memcpy(rights_id.data(), &field2, sizeof(u64));
@ -716,8 +717,9 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
std::tie(id, field1, field2);
});
if (iter2 != s128_file_id.end())
if (iter2 != s128_file_id.end()) {
WriteKeyToFile(category, iter2->first, key);
}
// Variable cases
if (id == S128KeyType::KeyArea) {
@ -745,16 +747,18 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
}
void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
if (s256_keys.find({id, field1, field2}) != s256_keys.end())
if (s256_keys.find({id, field1, field2}) != s256_keys.end() || key == Key256{}) {
return;
}
const auto iter = std::find_if(
s256_file_id.begin(), s256_file_id.end(),
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S256KeyType>> elem) {
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
std::tie(id, field1, field2);
});
if (iter != s256_file_id.end())
if (iter != s256_file_id.end()) {
WriteKeyToFile(KeyCategory::Standard, iter->first, key);
}
s256_keys[{id, field1, field2}] = key;
}

View File

@ -12,6 +12,10 @@
namespace FileSys {
constexpr u64 NAND_USER_SIZE = 0x680000000; // 26624 MiB
constexpr u64 NAND_SYSTEM_SIZE = 0xA0000000; // 2560 MiB
constexpr u64 NAND_TOTAL_SIZE = 0x747C00000; // 29820 MiB
BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
: nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
dump_root(std::move(dump_root_)),
@ -110,30 +114,29 @@ VirtualDir BISFactory::GetImageDirectory() const {
u64 BISFactory::GetSystemNANDFreeSpace() const {
const auto sys_dir = GetOrCreateDirectoryRelative(nand_root, "/system");
if (sys_dir == nullptr)
return 0;
if (sys_dir == nullptr) {
return GetSystemNANDTotalSpace();
}
return GetSystemNANDTotalSpace() - sys_dir->GetSize();
}
u64 BISFactory::GetSystemNANDTotalSpace() const {
return static_cast<u64>(Settings::values.nand_system_size);
return NAND_SYSTEM_SIZE;
}
u64 BISFactory::GetUserNANDFreeSpace() const {
const auto usr_dir = GetOrCreateDirectoryRelative(nand_root, "/user");
if (usr_dir == nullptr)
return 0;
return GetUserNANDTotalSpace() - usr_dir->GetSize();
// For some reason games such as BioShock 1 checks whether this is exactly 0x680000000 bytes.
// Set the free space to be 1 MiB less than the total as a workaround to this issue.
return GetUserNANDTotalSpace() - 0x100000;
}
u64 BISFactory::GetUserNANDTotalSpace() const {
return static_cast<u64>(Settings::values.nand_user_size);
return NAND_USER_SIZE;
}
u64 BISFactory::GetFullNANDTotalSpace() const {
return static_cast<u64>(Settings::values.nand_total_size);
return NAND_TOTAL_SIZE;
}
VirtualDir BISFactory::GetBCATDirectory(u64 title_id) const {

View File

@ -10,6 +10,8 @@
namespace FileSys {
constexpr u64 SDMC_TOTAL_SIZE = 0x10000000000; // 1 TiB
SDMCFactory::SDMCFactory(VirtualDir dir_)
: dir(std::move(dir_)), contents(std::make_unique<RegisteredCache>(
GetOrCreateDirectoryRelative(dir, "/Nintendo/Contents/registered"),
@ -46,7 +48,7 @@ u64 SDMCFactory::GetSDMCFreeSpace() const {
}
u64 SDMCFactory::GetSDMCTotalSpace() const {
return static_cast<u64>(Settings::values.sdmc_size);
return SDMC_TOTAL_SIZE;
}
} // namespace FileSys

View File

@ -112,19 +112,26 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
const auto new_path =
FileUtil::SanitizePath(new_path_, FileUtil::DirectorySeparator::PlatformDefault);
if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path))
return nullptr;
if (cache.find(old_path) != cache.end()) {
auto cached = cache[old_path];
if (!cached.expired()) {
auto file = cached.lock();
file->Open(new_path, "r+b");
cache.erase(old_path);
cache[new_path] = file;
auto file = cache[old_path].lock();
if (!cache[old_path].expired()) {
file->Close();
}
if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) ||
FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path)) {
return nullptr;
}
cache.erase(old_path);
file->Open(new_path, "r+b");
cache[new_path] = file;
} else {
UNREACHABLE();
return nullptr;
}
return OpenFile(new_path, Mode::ReadWrite);
}

View File

@ -29,7 +29,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
const float window_aspect_ratio = static_cast<float>(height) / width;
const float emulation_aspect_ratio = EmulationAspectRatio(
static_cast<AspectRatio>(Settings::values.aspect_ratio), window_aspect_ratio);
static_cast<AspectRatio>(Settings::values.aspect_ratio.GetValue()), window_aspect_ratio);
const Common::Rectangle<u32> screen_window_area{0, 0, width, height};
Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio);

View File

@ -123,7 +123,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
: kernel.CreateNewUserProcessID();
process->capabilities.InitializeForMetadatalessProcess();
std::mt19937 rng(Settings::values.rng_seed.value_or(0));
std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(0));
std::uniform_int_distribution<u64> distribution;
std::generate(process->random_entropy.begin(), process->random_entropy.end(),
[&] { return distribution(rng); });

View File

@ -6,6 +6,7 @@
// licensed under GPLv2 or later under exception provided by the author.
#include <algorithm>
#include <mutex>
#include <set>
#include <unordered_set>
#include <utility>
@ -31,22 +32,20 @@ GlobalScheduler::GlobalScheduler(KernelCore& kernel) : kernel{kernel} {}
GlobalScheduler::~GlobalScheduler() = default;
void GlobalScheduler::AddThread(std::shared_ptr<Thread> thread) {
global_list_guard.lock();
std::scoped_lock lock{global_list_guard};
thread_list.push_back(std::move(thread));
global_list_guard.unlock();
}
void GlobalScheduler::RemoveThread(std::shared_ptr<Thread> thread) {
global_list_guard.lock();
std::scoped_lock lock{global_list_guard};
thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
thread_list.end());
global_list_guard.unlock();
}
u32 GlobalScheduler::SelectThreads() {
ASSERT(is_locked);
const auto update_thread = [](Thread* thread, Scheduler& sched) {
sched.guard.lock();
std::scoped_lock lock{sched.guard};
if (thread != sched.selected_thread_set.get()) {
if (thread == nullptr) {
++sched.idle_selection_count;
@ -57,7 +56,6 @@ u32 GlobalScheduler::SelectThreads() {
sched.is_context_switch_pending || (sched.selected_thread_set != sched.current_thread);
sched.is_context_switch_pending = reschedule_pending;
std::atomic_thread_fence(std::memory_order_seq_cst);
sched.guard.unlock();
return reschedule_pending;
};
if (!is_reselection_pending.load()) {
@ -757,11 +755,12 @@ void Scheduler::OnSwitch(void* this_scheduler) {
void Scheduler::SwitchToCurrent() {
while (true) {
guard.lock();
selected_thread = selected_thread_set;
current_thread = selected_thread;
is_context_switch_pending = false;
guard.unlock();
{
std::scoped_lock lock{guard};
selected_thread = selected_thread_set;
current_thread = selected_thread;
is_context_switch_pending = false;
}
while (!is_context_switch_pending) {
if (current_thread != nullptr && !current_thread->IsHLEThread()) {
current_thread->context_guard.lock();

View File

@ -272,7 +272,7 @@ ISelfController::ISelfController(Core::System& system,
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{44, nullptr, "CreateManagedDisplaySeparableLayer"},
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
@ -462,6 +462,24 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
rb.Push(*layer_id);
}
void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
// TODO(Subv): Find out how AM determines the display to use, for now just
// create the layer in the Default display.
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
// side effects.
// TODO: Support multiple layers
const auto display_id = nvflinger->OpenDisplay("Default");
const auto layer_id = nvflinger->CreateLayer(*display_id);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
}
void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@ -731,14 +749,14 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
if (Settings::values.use_docked_mode) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
} else {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
}
}
@ -1389,7 +1407,19 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
u32 supported_languages = 0;
FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()};
const auto res = pm.GetControlMetadata();
const auto res = [this] {
const auto title_id = system.CurrentProcess()->GetTitleID();
FileSys::PatchManager pm{title_id};
auto res = pm.GetControlMetadata();
if (res.first != nullptr) {
return res;
}
FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)};
return pm_update.GetControlMetadata();
}();
if (res.first != nullptr) {
supported_languages = res.first->GetSupportedLanguages();
}

View File

@ -140,6 +140,7 @@ private:
void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx);
void SetAlbumImageOrientation(Kernel::HLERequestContext& ctx);
void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
void CreateManagedDisplaySeparableLayer(Kernel::HLERequestContext& ctx);
void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);

View File

@ -121,11 +121,83 @@ public:
{39, nullptr, "PrepareShutdown"},
{40, nullptr, "ListApplyDeltaTask"},
{41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
{42, nullptr, "Unknown1"},
{43, nullptr, "Unknown2"},
{44, nullptr, "Unknown3"},
{45, nullptr, "Unknown4"},
{46, nullptr, "Unknown5"},
{42, nullptr, "Unknown42"},
{43, nullptr, "Unknown43"},
{44, nullptr, "Unknown44"},
{45, nullptr, "Unknown45"},
{46, nullptr, "Unknown46"},
{47, nullptr, "Unknown47"},
{48, nullptr, "Unknown48"},
{49, nullptr, "Unknown49"},
{50, nullptr, "Unknown50"},
{51, nullptr, "Unknown51"},
{52, nullptr, "Unknown52"},
{53, nullptr, "Unknown53"},
{54, nullptr, "Unknown54"},
{55, nullptr, "Unknown55"},
{56, nullptr, "Unknown56"},
{57, nullptr, "Unknown57"},
{58, nullptr, "Unknown58"},
{59, nullptr, "Unknown59"},
{60, nullptr, "Unknown60"},
{61, nullptr, "Unknown61"},
{62, nullptr, "Unknown62"},
{63, nullptr, "Unknown63"},
{64, nullptr, "Unknown64"},
{65, nullptr, "Unknown65"},
{66, nullptr, "Unknown66"},
{67, nullptr, "Unknown67"},
{68, nullptr, "Unknown68"},
{69, nullptr, "Unknown69"},
{70, nullptr, "Unknown70"},
{71, nullptr, "Unknown71"},
{72, nullptr, "Unknown72"},
{73, nullptr, "Unknown73"},
{74, nullptr, "Unknown74"},
{75, nullptr, "Unknown75"},
{76, nullptr, "Unknown76"},
{77, nullptr, "Unknown77"},
{78, nullptr, "Unknown78"},
{79, nullptr, "Unknown79"},
{80, nullptr, "Unknown80"},
{81, nullptr, "Unknown81"},
{82, nullptr, "Unknown82"},
{83, nullptr, "Unknown83"},
{84, nullptr, "Unknown84"},
{85, nullptr, "Unknown85"},
{86, nullptr, "Unknown86"},
{87, nullptr, "Unknown87"},
{88, nullptr, "Unknown88"},
{89, nullptr, "Unknown89"},
{90, nullptr, "Unknown90"},
{91, nullptr, "Unknown91"},
{92, nullptr, "Unknown92"},
{93, nullptr, "Unknown93"},
{94, nullptr, "Unknown94"},
{95, nullptr, "Unknown95"},
{96, nullptr, "Unknown96"},
{97, nullptr, "Unknown97"},
{98, nullptr, "Unknown98"},
{99, nullptr, "Unknown99"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
{102, nullptr, "Unknown102"},
{103, nullptr, "Unknown103"},
{104, nullptr, "Unknown104"},
{105, nullptr, "Unknown105"},
{106, nullptr, "Unknown106"},
{107, nullptr, "Unknown107"},
{108, nullptr, "Unknown108"},
{109, nullptr, "Unknown109"},
{110, nullptr, "Unknown110"},
{111, nullptr, "Unknown111"},
{112, nullptr, "Unknown112"},
{113, nullptr, "Unknown113"},
{114, nullptr, "Unknown114"},
{115, nullptr, "Unknown115"},
{116, nullptr, "Unknown116"},
{117, nullptr, "Unknown117"},
{118, nullptr, "Unknown118"},
};
// clang-format on
@ -142,6 +214,7 @@ public:
{1, nullptr, "RefreshDebugAvailability"},
{2, nullptr, "ClearDebugResponse"},
{3, nullptr, "RegisterDebugResponse"},
{4, nullptr, "IsLargeResourceAvailable"},
};
// clang-format on
@ -164,6 +237,8 @@ public:
static const FunctionInfo functions[] = {
{0, nullptr, "RequestDeviceAuthenticationToken"},
{1, nullptr, "RequestCachedDeviceAuthenticationToken"},
{2, nullptr, "RequestEdgeToken"},
{3, nullptr, "RequestCachedEdgeToken"},
{100, nullptr, "RequestRegisterDeviceAccount"},
{101, nullptr, "RequestUnregisterDeviceAccount"},
{102, nullptr, "RequestDeviceAccountStatus"},
@ -181,7 +256,8 @@ public:
{305, nullptr, "RequestCreateVirtualAccount"},
{306, nullptr, "RequestDeviceLinkStatus"},
{400, nullptr, "GetAccountByVirtualAccount"},
{500, nullptr, "RequestSyncTicket"},
{401, nullptr, "GetVirtualAccount"},
{500, nullptr, "RequestSyncTicketLegacy"},
{501, nullptr, "RequestDownloadTicket"},
{502, nullptr, "RequestDownloadTicketForPrepurchasedContents"},
{503, nullptr, "RequestSyncTicket"},

View File

@ -30,6 +30,7 @@ public:
{23, nullptr, "DestroyToken"},
{24, nullptr, "DestroyTokenWithApplicationId"},
{25, nullptr, "QueryIsTokenValid"},
{26, nullptr, "ListenToMyApplicationId"},
{31, nullptr, "UploadTokenToBaaS"},
{32, nullptr, "DestroyTokenForBaaS"},
{33, nullptr, "CreateTokenForBaaS"},

View File

@ -104,7 +104,7 @@ IApplicationManagerInterface::IApplicationManagerInterface()
{94, nullptr, "LaunchApplication"},
{95, nullptr, "GetApplicationLaunchInfo"},
{96, nullptr, "AcquireApplicationLaunchInfo"},
{97, nullptr, "GetMainApplicationProgramIndex2"},
{97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
{98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
{99, nullptr, "LaunchDevMenu"},
{100, nullptr, "ResetToFactorySettings"},
@ -254,7 +254,7 @@ IApplicationManagerInterface::IApplicationManagerInterface()
{2170, nullptr, "GetRightsEnvironmentStatus"},
{2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
{2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
{2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"},
{2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
{2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
{2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
{2199, nullptr, "GetRightsEnvironmentCountForDebug"},
@ -366,7 +366,8 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
// Get language code from settings
const auto language_code = Set::GetLanguageCodeFromIndex(Settings::values.language_index);
const auto language_code =
Set::GetLanguageCodeFromIndex(Settings::values.language_index.GetValue());
// Convert to application language, get priority list
const auto application_language = ConvertToApplicationLanguage(language_code);
@ -445,8 +446,8 @@ IApplicationVersionInterface::IApplicationVersionInterface()
IApplicationVersionInterface::~IApplicationVersionInterface() = default;
IContentManagerInterface::IContentManagerInterface()
: ServiceFramework{"IContentManagerInterface"} {
IContentManagementInterface::IContentManagementInterface()
: ServiceFramework{"IContentManagementInterface"} {
// clang-format off
static const FunctionInfo functions[] = {
{11, nullptr, "CalculateApplicationOccupiedSize"},
@ -463,7 +464,7 @@ IContentManagerInterface::IContentManagerInterface()
RegisterHandlers(functions);
}
IContentManagerInterface::~IContentManagerInterface() = default;
IContentManagementInterface::~IContentManagementInterface() = default;
IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface"} {
// clang-format off
@ -545,7 +546,7 @@ NS::NS(const char* name) : ServiceFramework{name} {
{7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
{7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"},
{7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
{7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"},
{7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
{7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
};
// clang-format on
@ -572,9 +573,9 @@ public:
{6, nullptr, "TerminateApplication"},
{7, nullptr, "PrepareLaunchProgramFromHost"},
{8, nullptr, "LaunchApplication"},
{9, nullptr, "LaunchApplicationWithStorageId"},
{10, nullptr, "TerminateApplication2"},
{11, nullptr, "GetRunningApplicationProcessId"},
{9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
{10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
{11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
{12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActive"},
{13, nullptr, "CreateApplicationResourceForDevelop"},
{14, nullptr, "IsPreomiaForDevelop"},
@ -636,6 +637,10 @@ public:
{9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
{10, nullptr, "NotifySystemUpdateForContentDelivery"},
{11, nullptr, "PrepareShutdown"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "DestroySystemUpdateTask"},
{17, nullptr, "RequestSendSystemUpdate"},
{18, nullptr, "GetSendSystemUpdateProgress"},

View File

@ -40,10 +40,10 @@ public:
~IApplicationVersionInterface() override;
};
class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> {
class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
public:
explicit IContentManagerInterface();
~IContentManagerInterface() override;
explicit IContentManagementInterface();
~IContentManagementInterface() override;
};
class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {

View File

@ -163,7 +163,7 @@ PL_U::PL_U(Core::System& system)
{5, &PL_U::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
{6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"},
{100, nullptr, "RequestApplicationFunctionAuthorization"},
{101, nullptr, "RequestApplicationFunctionAuthorizationForSystem"},
{101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
{102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
{1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
{1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},

View File

@ -144,7 +144,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
}
}
void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
void NVDRV::SetAruid(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
pid = rp.Pop<u64>();
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x{:X}", pid);
@ -154,7 +154,7 @@ void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(0);
}
void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) {
void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
@ -187,13 +187,14 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
{4, &NVDRV::QueryEvent, "QueryEvent"},
{5, nullptr, "MapSharedMem"},
{6, &NVDRV::GetStatus, "GetStatus"},
{7, nullptr, "ForceSetClientPID"},
{8, &NVDRV::SetClientPID, "SetClientPID"},
{7, nullptr, "SetAruidForTest"},
{8, &NVDRV::SetAruid, "SetAruid"},
{9, &NVDRV::DumpGraphicsMemoryInfo, "DumpGraphicsMemoryInfo"},
{10, nullptr, "InitializeDevtools"},
{11, &NVDRV::Ioctl2, "Ioctl2"},
{12, &NVDRV::Ioctl3, "Ioctl3"},
{13, &NVDRV::FinishInitialize, "FinishInitialize"},
{13, &NVDRV::SetGraphicsFirmwareMemoryMarginEnabled,
"SetGraphicsFirmwareMemoryMarginEnabled"},
};
RegisterHandlers(functions);
}

View File

@ -29,8 +29,8 @@ private:
void Close(Kernel::HLERequestContext& ctx);
void Initialize(Kernel::HLERequestContext& ctx);
void QueryEvent(Kernel::HLERequestContext& ctx);
void SetClientPID(Kernel::HLERequestContext& ctx);
void FinishInitialize(Kernel::HLERequestContext& ctx);
void SetAruid(Kernel::HLERequestContext& ctx);
void SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx);
void GetStatus(Kernel::HLERequestContext& ctx);
void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx);
void IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version);

View File

@ -10,19 +10,19 @@ namespace Service::Nvidia {
NVMEMP::NVMEMP() : ServiceFramework("nvmemp") {
static const FunctionInfo functions[] = {
{0, &NVMEMP::Cmd0, "Cmd0"},
{1, &NVMEMP::Cmd1, "Cmd1"},
{0, &NVMEMP::Open, "Open"},
{1, &NVMEMP::GetAruid, "GetAruid"},
};
RegisterHandlers(functions);
}
NVMEMP::~NVMEMP() = default;
void NVMEMP::Cmd0(Kernel::HLERequestContext& ctx) {
void NVMEMP::Open(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED();
}
void NVMEMP::Cmd1(Kernel::HLERequestContext& ctx) {
void NVMEMP::GetAruid(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED();
}

View File

@ -14,8 +14,8 @@ public:
~NVMEMP() override;
private:
void Cmd0(Kernel::HLERequestContext& ctx);
void Cmd1(Kernel::HLERequestContext& ctx);
void Open(Kernel::HLERequestContext& ctx);
void GetAruid(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Nvidia

View File

@ -36,6 +36,9 @@ public:
{18, nullptr, "ReleaseIrq"},
{19, nullptr, "SetIrqEnable"},
{20, nullptr, "SetAspmEnable"},
{21, nullptr, "SetResetUponResumeEnable"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
};
// clang-format on

View File

@ -42,6 +42,9 @@ public:
{24, nullptr, "GetModuleStateTable"},
{25, nullptr, "GetPowerDomainStateTable"},
{26, nullptr, "GetFuseInfo"},
{27, nullptr, "GetDramId"},
{28, nullptr, "IsPoweredOn"},
{29, nullptr, "GetVoltage"},
};
// clang-format on

View File

@ -78,13 +78,13 @@ public:
: ServiceFramework{"pm:dmnt"}, kernel(kernel) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetDebugProcesses"},
{1, nullptr, "StartDebugProcess"},
{2, &DebugMonitor::GetTitlePid, "GetTitlePid"},
{3, nullptr, "EnableDebugForTitleId"},
{4, &DebugMonitor::GetApplicationPid, "GetApplicationPid"},
{5, nullptr, "EnableDebugForApplication"},
{6, nullptr, "DisableDebug"},
{0, nullptr, "GetJitDebugProcessIdList"},
{1, nullptr, "StartProcess"},
{2, &DebugMonitor::GetProcessId, "GetProcessId"},
{3, nullptr, "HookToCreateProcess"},
{4, &DebugMonitor::GetApplicationProcessId, "GetApplicationProcessId"},
{5, nullptr, "HookToCreateApplicationProgress"},
{6, nullptr, "ClearHook"},
};
// clang-format on
@ -92,7 +92,7 @@ public:
}
private:
void GetTitlePid(Kernel::HLERequestContext& ctx) {
void GetProcessId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto title_id = rp.PopRaw<u64>();
@ -114,7 +114,7 @@ private:
rb.Push((*process)->GetProcessID());
}
void GetApplicationPid(Kernel::HLERequestContext& ctx) {
void GetApplicationProcessId(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called");
GetApplicationPidGeneric(ctx, kernel.GetProcessList());
}
@ -163,15 +163,15 @@ public:
: ServiceFramework{"pm:shell"}, kernel(kernel) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "LaunchProcess"},
{1, nullptr, "TerminateProcessByPid"},
{2, nullptr, "TerminateProcessByTitleId"},
{3, nullptr, "GetProcessEventWaiter"},
{4, nullptr, "GetProcessEventType"},
{0, nullptr, "LaunchProgram"},
{1, nullptr, "TerminateProcess"},
{2, nullptr, "TerminateProgram"},
{3, nullptr, "GetProcessEventHandle"},
{4, nullptr, "GetProcessEventInfo"},
{5, nullptr, "NotifyBootFinished"},
{6, &Shell::GetApplicationPid, "GetApplicationPid"},
{6, &Shell::GetApplicationProcessIdForShell, "GetApplicationProcessIdForShell"},
{7, nullptr, "BoostSystemMemoryResourceLimit"},
{8, nullptr, "EnableAdditionalSystemThreads"},
{8, nullptr, "BoostApplicationThreadResourceLimit"},
{9, nullptr, "GetBootFinishedEventHandle"},
};
// clang-format on
@ -180,7 +180,7 @@ public:
}
private:
void GetApplicationPid(Kernel::HLERequestContext& ctx) {
void GetApplicationProcessIdForShell(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PM, "called");
GetApplicationPidGeneric(ctx, kernel.GetProcessList());
}

View File

@ -42,6 +42,11 @@ public:
{40101, nullptr, "SetUserAgreementCheckEnabled"},
{50100, nullptr, "ReadAllApplicationReportFiles"},
{90100, nullptr, "ReadAllReportFiles"},
{90101, nullptr, "Unknown90101"},
{90102, nullptr, "Unknown90102"},
{90200, nullptr, "GetStatistics"},
{90201, nullptr, "GetThroughputHistory"},
{90300, nullptr, "GetLastUploadError"},
};
// clang-format on

View File

@ -24,6 +24,8 @@ public:
{4, nullptr, "Cancel"},
{5, nullptr, "PrintModuleInformation"},
{6, nullptr, "GetModuleInformation"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
};
// clang-format on

View File

@ -35,6 +35,7 @@ public:
{15, nullptr, "GetBatteryAgePercentage"},
{16, nullptr, "GetBatteryChargeInfoEvent"},
{17, nullptr, "GetBatteryChargeInfoFields"},
{18, nullptr, "GetBatteryChargeCalibratedEvent"},
};
// clang-format on

View File

@ -91,7 +91,7 @@ void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t m
}
void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
const auto language_code = available_language_codes[Settings::values.language_index];
const auto language_code = available_language_codes[Settings::values.language_index.GetValue()];
const auto key_code =
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
[=](const auto& element) { return element.first == language_code; });
@ -99,7 +99,7 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
if (key_code == language_to_layout.cend()) {
LOG_ERROR(Service_SET,
"Could not find keyboard layout for language index {}, defaulting to English us",
Settings::values.language_index);
Settings::values.language_index.GetValue());
} else {
layout = key_code->second;
}
@ -163,11 +163,11 @@ void SET::GetQuestFlag(Kernel::HLERequestContext& ctx) {
}
void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index);
LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue());
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.PushEnum(available_language_codes[Settings::values.language_index]);
rb.PushEnum(available_language_codes[Settings::values.language_index.GetValue()]);
}
void SET::GetRegionCode(Kernel::HLERequestContext& ctx) {
@ -175,7 +175,7 @@ void SET::GetRegionCode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(Settings::values.region_index);
rb.Push(Settings::values.region_index.GetValue());
}
void SET::GetKeyCodeMap(Kernel::HLERequestContext& ctx) {

View File

@ -12,7 +12,7 @@
namespace Service::SM {
void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain");
LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId());
ctx.Session()->ConvertToDomain();
@ -22,7 +22,7 @@ void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(1); // Converted sessions start with 1 request handler
}
void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong
// and that we probably want to actually make an entirely new Session, but we still need to
// verify this on hardware.
@ -33,10 +33,10 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
rb.PushMoveObjects(ctx.Session()->GetParent()->Client());
}
void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called, using DuplicateSession");
void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called, using CloneCurrentObject");
DuplicateSession(ctx);
CloneCurrentObject(ctx);
}
void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
@ -47,13 +47,14 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push<u16>(0x1000);
}
// https://switchbrew.org/wiki/IPC_Marshalling
Controller::Controller() : ServiceFramework("IpcController") {
static const FunctionInfo functions[] = {
{0x00000000, &Controller::ConvertSessionToDomain, "ConvertSessionToDomain"},
{0x00000001, nullptr, "ConvertDomainToSession"},
{0x00000002, &Controller::DuplicateSession, "DuplicateSession"},
{0x00000003, &Controller::QueryPointerBufferSize, "QueryPointerBufferSize"},
{0x00000004, &Controller::DuplicateSessionEx, "DuplicateSessionEx"},
{0, &Controller::ConvertCurrentObjectToDomain, "ConvertCurrentObjectToDomain"},
{1, nullptr, "CopyFromCurrentDomain"},
{2, &Controller::CloneCurrentObject, "CloneCurrentObject"},
{3, &Controller::QueryPointerBufferSize, "QueryPointerBufferSize"},
{4, &Controller::CloneCurrentObjectEx, "CloneCurrentObjectEx"},
};
RegisterHandlers(functions);
}

View File

@ -14,9 +14,9 @@ public:
~Controller() override;
private:
void ConvertSessionToDomain(Kernel::HLERequestContext& ctx);
void DuplicateSession(Kernel::HLERequestContext& ctx);
void DuplicateSessionEx(Kernel::HLERequestContext& ctx);
void ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx);
void CloneCurrentObject(Kernel::HLERequestContext& ctx);
void CloneCurrentObjectEx(Kernel::HLERequestContext& ctx);
void QueryPointerBufferSize(Kernel::HLERequestContext& ctx);
};

View File

@ -14,6 +14,7 @@ NSD::NSD(const char* name) : ServiceFramework(name) {
{12, nullptr, "GetDeviceId"},
{13, nullptr, "DeleteSettings"},
{14, nullptr, "ImportSettings"},
{15, nullptr, "SetChangeEnvironmentIdentifierDisabled"},
{20, nullptr, "Resolve"},
{21, nullptr, "ResolveEx"},
{30, nullptr, "GetNasServiceSetting"},
@ -28,6 +29,11 @@ NSD::NSD(const char* name) : ServiceFramework(name) {
{60, nullptr, "ReadSaveDataFromFsForTest"},
{61, nullptr, "WriteSaveDataToFsForTest"},
{62, nullptr, "DeleteSaveDataOfFsForTest"},
{63, nullptr, "IsChangeEnvironmentIdentifierDisabled"},
{64, nullptr, "SetWithoutDomainExchangeFqdns"},
{100, nullptr, "GetApplicationServerEnvironmentType"},
{101, nullptr, "SetApplicationServerEnvironmentType"},
{102, nullptr, "DeleteApplicationServerEnvironmentType"},
};
// clang-format on

View File

@ -7,7 +7,7 @@
namespace Service::Sockets {
void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) {
void SFDNSRES::GetAddrInfoRequest(Kernel::HLERequestContext& ctx) {
struct Parameters {
u8 use_nsd_resolve;
u32 unknown;
@ -29,15 +29,20 @@ SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") {
static const FunctionInfo functions[] = {
{0, nullptr, "SetDnsAddressesPrivate"},
{1, nullptr, "GetDnsAddressPrivate"},
{2, nullptr, "GetHostByName"},
{3, nullptr, "GetHostByAddr"},
{4, nullptr, "GetHostStringError"},
{5, nullptr, "GetGaiStringError"},
{6, &SFDNSRES::GetAddrInfo, "GetAddrInfo"},
{7, nullptr, "GetNameInfo"},
{8, nullptr, "RequestCancelHandle"},
{9, nullptr, "CancelSocketCall"},
{11, nullptr, "ClearDnsIpServerAddressArray"},
{2, nullptr, "GetHostByNameRequest"},
{3, nullptr, "GetHostByAddrRequest"},
{4, nullptr, "GetHostStringErrorRequest"},
{5, nullptr, "GetGaiStringErrorRequest"},
{6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
{7, nullptr, "GetNameInfoRequest"},
{8, nullptr, "RequestCancelHandleRequest"},
{9, nullptr, "CancelRequest"},
{10, nullptr, "GetHostByNameRequestWithOptions"},
{11, nullptr, "GetHostByAddrRequestWithOptions"},
{12, nullptr, "GetAddrInfoRequestWithOptions"},
{13, nullptr, "GetNameInfoRequestWithOptions"},
{14, nullptr, "ResolverSetOptionRequest"},
{15, nullptr, "ResolverGetOptionRequest"},
};
RegisterHandlers(functions);
}

View File

@ -15,7 +15,7 @@ public:
~SFDNSRES() override;
private:
void GetAddrInfo(Kernel::HLERequestContext& ctx);
void GetAddrInfoRequest(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Sockets

View File

@ -19,7 +19,7 @@ namespace Service::SPL {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)),
rng(Settings::values.rng_seed.value_or(std::time(nullptr))) {}
rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))) {}
Module::Interface::~Interface() = default;

View File

@ -9,35 +9,36 @@ namespace Service::SPL {
SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "spl:") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "UserExpMod"},
{1, nullptr, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GetRandomBytes"},
{9, nullptr, "LoadSecureExpModKey"},
{10, nullptr, "SecureExpMod"},
{9, nullptr, "ImportLotusKey"},
{10, nullptr, "DecryptLotusMessage"},
{11, nullptr, "IsDevelopment"},
{12, nullptr, "GenerateSpecificAesKey"},
{13, nullptr, "DecryptPrivk"},
{13, nullptr, "DecryptDeviceUniqueData"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "DecryptAesCtr"},
{15, nullptr, "CryptAesCtr"},
{16, nullptr, "ComputeCmac"},
{17, nullptr, "LoadRsaOaepKey"},
{18, nullptr, "UnwrapRsaOaepWrappedTitleKey"},
{17, nullptr, "ImportEsKey"},
{18, nullptr, "UnwrapTitleKey"},
{19, nullptr, "LoadTitleKey"},
{20, nullptr, "UnwrapAesWrappedTitleKey"},
{21, nullptr, "LockAesEngine"},
{22, nullptr, "UnlockAesEngine"},
{23, nullptr, "GetSplWaitEvent"},
{24, nullptr, "SetSharedData"},
{25, nullptr, "GetSharedData"},
{26, nullptr, "ImportSslRsaKey"},
{27, nullptr, "SecureExpModWithSslKey"},
{28, nullptr, "ImportEsRsaKey"},
{29, nullptr, "SecureExpModWithEsKey"},
{30, nullptr, "EncryptManuRsaKeyForImport"},
{31, nullptr, "GetPackage2Hash"},
{20, nullptr, "PrepareEsCommonKey"},
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{26, nullptr, "DecryptAndStoreSslClientCertKey"},
{27, nullptr, "ModularExponentiateWithSslClientCertKey"},
{28, nullptr, "DecryptAndStoreDrmDeviceCertKey"},
{29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"},
{30, nullptr, "ReencryptDeviceUniqueData "},
{31, nullptr, "PrepareEsArchiveKey"}, // This is also GetPackage2Hash?
{32, nullptr, "LoadPreparedAesKey"},
};
RegisterHandlers(functions);
}

View File

@ -90,6 +90,13 @@ public:
: ServiceFramework("ISteadyClock"), clock_core{clock_core}, system{system} {
static const FunctionInfo functions[] = {
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
{2, nullptr, "GetTestOffset"},
{3, nullptr, "SetTestOffset"},
{100, nullptr, "GetRtcValue"},
{101, nullptr, "IsRtcResetDetected"},
{102, nullptr, "GetSetupResultValue"},
{200, nullptr, "GetInternalOffset"},
{201, nullptr, "SetInternalOffset"},
};
RegisterHandlers(functions);
}

View File

@ -20,7 +20,7 @@ public:
static const FunctionInfo functions[] = {
{0, nullptr, "GetDsEndpoint"},
{1, nullptr, "GetSetupEvent"},
{2, nullptr, "Unknown"},
{2, nullptr, "Unknown2"},
{3, nullptr, "EnableInterface"},
{4, nullptr, "DisableInterface"},
{5, nullptr, "CtrlInPostBufferAsync"},
@ -55,6 +55,7 @@ public:
{9, nullptr, "SetBinaryObjectStore"},
{10, nullptr, "Enable"},
{11, nullptr, "Disable"},
{12, nullptr, "Unknown12"},
};
// clang-format on
@ -69,13 +70,13 @@ public:
static const FunctionInfo functions[] = {
{0, nullptr, "Open"},
{1, nullptr, "Close"},
{2, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Populate"},
{4, nullptr, "PostBufferAsync"},
{5, nullptr, "GetXferReport"},
{6, nullptr, "PostBufferMultiAsync"},
{7, nullptr, "Unknown3"},
{8, nullptr, "Unknown4"},
{7, nullptr, "Unknown7"},
{8, nullptr, "Unknown8"},
};
// clang-format on
@ -88,13 +89,13 @@ public:
explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{0, nullptr, "Unknown0"},
{1, nullptr, "SetInterface"},
{2, nullptr, "GetInterface"},
{3, nullptr, "GetAlternateInterface"},
{4, nullptr, "GetCurrentFrame"},
{5, nullptr, "CtrlXferAsync"},
{6, nullptr, "Unknown2"},
{6, nullptr, "Unknown6"},
{7, nullptr, "GetCtrlXferReport"},
{8, nullptr, "ResetDevice"},
{9, nullptr, "OpenUsbEp"},
@ -118,7 +119,7 @@ public:
{5, nullptr, "DestroyInterfaceAvailableEvent"},
{6, nullptr, "GetInterfaceStateChangeEvent"},
{7, nullptr, "AcquireUsbIf"},
{8, nullptr, "Unknown1"},
{8, nullptr, "Unknown8"},
};
// clang-format on
@ -179,8 +180,8 @@ public:
{4, nullptr, "GetFwRevision"},
{5, nullptr, "GetManufacturerId"},
{6, nullptr, "GetDeviceId"},
{7, nullptr, "Unknown1"},
{8, nullptr, "Unknown2"},
{7, nullptr, "Unknown7"},
{8, nullptr, "Unknown8"},
};
// clang-format on
@ -215,12 +216,12 @@ public:
explicit USB_PM() : ServiceFramework{"usb:pm"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "Unknown6"},
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, nullptr, "Unknown5"},
};
// clang-format on

View File

@ -519,9 +519,9 @@ private:
IGBPConnectRequestParcel request{ctx.ReadBuffer()};
IGBPConnectResponseParcel response{
static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) *
Settings::values.resolution_factor),
Settings::values.resolution_factor.GetValue()),
static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) *
Settings::values.resolution_factor)};
Settings::values.resolution_factor.GetValue())};
ctx.WriteBuffer(response.Serialize());
break;
}
@ -700,6 +700,7 @@ public:
{3215, nullptr, "SetDisplayGamma"},
{3216, nullptr, "GetDisplayCmuLuma"},
{3217, nullptr, "SetDisplayCmuLuma"},
{6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
{8225, nullptr, "GetSharedBufferMemoryHandleId"},
{8250, nullptr, "OpenSharedLayer"},
{8251, nullptr, "CloseSharedLayer"},
@ -748,14 +749,14 @@ private:
if (Settings::values.use_docked_mode) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
} else {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
}
rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
@ -785,6 +786,7 @@ public:
{2300, nullptr, "AcquireLayerTexturePresentingEvent"},
{2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
{2302, nullptr, "GetDisplayHotplugEvent"},
{2303, nullptr, "GetDisplayModeChangedEvent"},
{2402, nullptr, "GetDisplayHotplugState"},
{2501, nullptr, "GetCompositorErrorInfo"},
{2601, nullptr, "GetDisplayErrorEvent"},
@ -1029,9 +1031,9 @@ private:
// between docked and undocked dimensions. We take the liberty of applying
// the resolution scaling factor here.
rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) *
static_cast<u32>(Settings::values.resolution_factor));
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
}
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
@ -1064,8 +1066,8 @@ private:
LOG_WARNING(Service_VI, "(STUBBED) called");
DisplayInfo display_info;
display_info.width *= static_cast<u64>(Settings::values.resolution_factor);
display_info.height *= static_cast<u64>(Settings::values.resolution_factor);
display_info.width *= static_cast<u64>(Settings::values.resolution_factor.GetValue());
display_info.height *= static_cast<u64>(Settings::values.resolution_factor.GetValue());
ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);

View File

@ -12,6 +12,7 @@ VI_U::VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
: ServiceFramework{"vi:u"}, nv_flinger{std::move(nv_flinger)} {
static const FunctionInfo functions[] = {
{0, &VI_U::GetDisplayService, "GetDisplayService"},
{1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
};
RegisterHandlers(functions);
}

View File

@ -15,34 +15,37 @@ public:
explicit WLANInfra() : ServiceFramework{"wlan:inf"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{0, nullptr, "OpenMode"},
{1, nullptr, "CloseMode"},
{2, nullptr, "GetMacAddress"},
{3, nullptr, "StartScan"},
{4, nullptr, "StopScan"},
{5, nullptr, "Connect"},
{6, nullptr, "CancelConnect"},
{7, nullptr, "Disconnect"},
{8, nullptr, "Unknown3"},
{9, nullptr, "Unknown4"},
{8, nullptr, "GetConnectionEvent"},
{9, nullptr, "GetConnectionStatus"},
{10, nullptr, "GetState"},
{11, nullptr, "GetScanResult"},
{12, nullptr, "GetRssi"},
{13, nullptr, "ChangeRxAntenna"},
{14, nullptr, "Unknown5"},
{15, nullptr, "Unknown6"},
{14, nullptr, "GetFwVersion"},
{15, nullptr, "RequestSleep"},
{16, nullptr, "RequestWakeUp"},
{17, nullptr, "RequestIfUpDown"},
{18, nullptr, "Unknown7"},
{19, nullptr, "Unknown8"},
{20, nullptr, "Unknown9"},
{21, nullptr, "Unknown10"},
{22, nullptr, "Unknown11"},
{23, nullptr, "Unknown12"},
{24, nullptr, "Unknown13"},
{25, nullptr, "Unknown14"},
{26, nullptr, "Unknown15"},
{27, nullptr, "Unknown16"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
{25, nullptr, "Unknown25"},
{26, nullptr, "Unknown26"},
{27, nullptr, "Unknown27"},
{28, nullptr, "Unknown28"},
{29, nullptr, "Unknown29"},
{30, nullptr, "Unknown30"},
};
// clang-format on
@ -55,12 +58,12 @@ public:
explicit WLANLocal() : ServiceFramework{"wlan:lcl"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "Unknown6"},
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, nullptr, "Unknown5"},
{6, nullptr, "GetMacAddress"},
{7, nullptr, "CreateBss"},
{8, nullptr, "DestroyBss"},
@ -72,38 +75,42 @@ public:
{14, nullptr, "CancelJoin"},
{15, nullptr, "Disconnect"},
{16, nullptr, "SetBeaconLostCount"},
{17, nullptr, "Unknown7"},
{18, nullptr, "Unknown8"},
{19, nullptr, "Unknown9"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "GetBssIndicationEvent"},
{21, nullptr, "GetBssIndicationInfo"},
{22, nullptr, "GetState"},
{23, nullptr, "GetAllowedChannels"},
{24, nullptr, "AddIe"},
{25, nullptr, "DeleteIe"},
{26, nullptr, "Unknown10"},
{27, nullptr, "Unknown11"},
{26, nullptr, "Unknown26"},
{27, nullptr, "Unknown27"},
{28, nullptr, "CreateRxEntry"},
{29, nullptr, "DeleteRxEntry"},
{30, nullptr, "Unknown12"},
{31, nullptr, "Unknown13"},
{30, nullptr, "Unknown30"},
{31, nullptr, "Unknown31"},
{32, nullptr, "AddMatchingDataToRxEntry"},
{33, nullptr, "RemoveMatchingDataFromRxEntry"},
{34, nullptr, "GetScanResult"},
{35, nullptr, "Unknown14"},
{35, nullptr, "Unknown35"},
{36, nullptr, "SetActionFrameWithBeacon"},
{37, nullptr, "CancelActionFrameWithBeacon"},
{38, nullptr, "CreateRxEntryForActionFrame"},
{39, nullptr, "DeleteRxEntryForActionFrame"},
{40, nullptr, "Unknown15"},
{41, nullptr, "Unknown16"},
{40, nullptr, "Unknown40"},
{41, nullptr, "Unknown41"},
{42, nullptr, "CancelGetActionFrame"},
{43, nullptr, "GetRssi"},
{44, nullptr, "Unknown17"},
{45, nullptr, "Unknown18"},
{46, nullptr, "Unknown19"},
{47, nullptr, "Unknown20"},
{48, nullptr, "Unknown21"},
{44, nullptr, "Unknown44"},
{45, nullptr, "Unknown45"},
{46, nullptr, "Unknown46"},
{47, nullptr, "Unknown47"},
{48, nullptr, "Unknown48"},
{49, nullptr, "Unknown49"},
{50, nullptr, "Unknown50"},
{51, nullptr, "Unknown51"},
{52, nullptr, "Unknown52"},
};
// clang-format on
@ -142,18 +149,19 @@ public:
explicit WLANSocketManager() : ServiceFramework{"wlan:soc"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "Unknown6"},
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, nullptr, "Unknown5"},
{6, nullptr, "GetMacAddress"},
{7, nullptr, "SwitchTsfTimerFunction"},
{8, nullptr, "Unknown7"},
{9, nullptr, "Unknown8"},
{10, nullptr, "Unknown9"},
{11, nullptr, "Unknown10"},
{8, nullptr, "Unknown8"},
{9, nullptr, "Unknown9"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
};
// clang-format on

View File

@ -119,13 +119,14 @@ double PerfStats::GetLastFrameTimeScale() {
}
void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) {
if (!Settings::values.use_frame_limit || Settings::values.use_multi_core) {
if (!Settings::values.use_frame_limit.GetValue() ||
Settings::values.use_multi_core.GetValue()) {
return;
}
auto now = Clock::now();
const double sleep_scale = Settings::values.frame_limit / 100.0;
const double sleep_scale = Settings::values.frame_limit.GetValue() / 100.0;
// Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current
// speed percent or it will clamp too much and prevent this from properly limiting to that

View File

@ -62,6 +62,7 @@ const std::array<const char*, NumMouseButtons> mapping = {{
}
Values values = {};
bool configuring_global = true;
std::string GetTimeZoneString() {
static constexpr std::array<const char*, 46> timezones{{
@ -73,9 +74,9 @@ std::string GetTimeZoneString() {
"UCT", "Universal", "UTC", "W-SU", "WET", "Zulu",
}};
ASSERT(Settings::values.time_zone_index < timezones.size());
ASSERT(Settings::values.time_zone_index.GetValue() < timezones.size());
return timezones[Settings::values.time_zone_index];
return timezones[Settings::values.time_zone_index.GetValue()];
}
void Apply() {
@ -97,25 +98,25 @@ void LogSetting(const std::string& name, const T& value) {
void LogSettings() {
LOG_INFO(Config, "yuzu Configuration:");
LogSetting("System_UseDockedMode", Settings::values.use_docked_mode);
LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0));
LogSetting("Controls_UseDockedMode", Settings::values.use_docked_mode);
LogSetting("System_RngSeed", Settings::values.rng_seed.GetValue().value_or(0));
LogSetting("System_CurrentUser", Settings::values.current_user);
LogSetting("System_LanguageIndex", Settings::values.language_index);
LogSetting("System_RegionIndex", Settings::values.region_index);
LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index);
LogSetting("Core_UseMultiCore", Settings::values.use_multi_core);
LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor);
LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit);
LogSetting("Renderer_FrameLimit", Settings::values.frame_limit);
LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache);
LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy);
LogSetting("System_LanguageIndex", Settings::values.language_index.GetValue());
LogSetting("System_RegionIndex", Settings::values.region_index.GetValue());
LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index.GetValue());
LogSetting("Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor.GetValue());
LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue());
LogSetting("Renderer_FrameLimit", Settings::values.frame_limit.GetValue());
LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache.GetValue());
LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy.GetValue());
LogSetting("Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation);
LogSetting("Renderer_UseVsync", Settings::values.use_vsync);
LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders);
LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy);
Settings::values.use_asynchronous_gpu_emulation.GetValue());
LogSetting("Renderer_UseVsync", Settings::values.use_vsync.GetValue());
LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders.GetValue());
LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy.GetValue());
LogSetting("Audio_OutputEngine", Settings::values.sink_id);
LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching);
LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching.GetValue());
LogSetting("Audio_OutputDevice", Settings::values.audio_device_id);
LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd);
LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir));
@ -131,15 +132,56 @@ float Volume() {
if (values.audio_muted) {
return 0.0f;
}
return values.volume;
return values.volume.GetValue();
}
bool IsGPULevelExtreme() {
return values.gpu_accuracy == GPUAccuracy::Extreme;
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme;
}
bool IsGPULevelHigh() {
return values.gpu_accuracy == GPUAccuracy::Extreme || values.gpu_accuracy == GPUAccuracy::High;
return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme ||
values.gpu_accuracy.GetValue() == GPUAccuracy::High;
}
void RestoreGlobalState() {
// If a game is running, DO NOT restore the global settings state
if (Core::System::GetInstance().IsPoweredOn()) {
return;
}
// Audio
values.enable_audio_stretching.SetGlobal(true);
values.volume.SetGlobal(true);
// Core
values.use_multi_core.SetGlobal(true);
// Renderer
values.renderer_backend.SetGlobal(true);
values.vulkan_device.SetGlobal(true);
values.aspect_ratio.SetGlobal(true);
values.max_anisotropy.SetGlobal(true);
values.use_frame_limit.SetGlobal(true);
values.frame_limit.SetGlobal(true);
values.use_disk_shader_cache.SetGlobal(true);
values.gpu_accuracy.SetGlobal(true);
values.use_asynchronous_gpu_emulation.SetGlobal(true);
values.use_vsync.SetGlobal(true);
values.use_assembly_shaders.SetGlobal(true);
values.use_fast_gpu_time.SetGlobal(true);
values.force_30fps_mode.SetGlobal(true);
values.bg_red.SetGlobal(true);
values.bg_green.SetGlobal(true);
values.bg_blue.SetGlobal(true);
// System
values.language_index.SetGlobal(true);
values.region_index.SetGlobal(true);
values.time_zone_index.SetGlobal(true);
values.rng_seed.SetGlobal(true);
values.custom_rtc.SetGlobal(true);
values.sound_index.SetGlobal(true);
}
} // namespace Settings

View File

@ -346,31 +346,6 @@ struct TouchscreenInput {
u32 rotation_angle;
};
enum class NANDTotalSize : u64 {
S29_1GB = 0x747C00000ULL,
};
enum class NANDUserSize : u64 {
S26GB = 0x680000000ULL,
};
enum class NANDSystemSize : u64 {
S2_5GB = 0xA0000000,
};
enum class SDMCSize : u64 {
S1GB = 0x40000000,
S2GB = 0x80000000,
S4GB = 0x100000000ULL,
S8GB = 0x200000000ULL,
S16GB = 0x400000000ULL,
S32GB = 0x800000000ULL,
S64GB = 0x1000000000ULL,
S128GB = 0x2000000000ULL,
S256GB = 0x4000000000ULL,
S1TB = 0x10000000000ULL,
};
enum class RendererBackend {
OpenGL = 0,
Vulkan = 1,
@ -382,20 +357,102 @@ enum class GPUAccuracy : u32 {
Extreme = 2,
};
enum class CPUAccuracy {
Accurate = 0,
DebugMode = 1,
};
extern bool configuring_global;
template <typename Type>
class Setting final {
public:
Setting() = default;
explicit Setting(Type val) : global{val} {}
~Setting() = default;
void SetGlobal(bool to_global) {
use_global = to_global;
}
bool UsingGlobal() const {
return use_global;
}
Type GetValue(bool need_global = false) const {
if (use_global || need_global) {
return global;
}
return local;
}
void SetValue(const Type& value) {
if (use_global) {
global = value;
} else {
local = value;
}
}
private:
bool use_global = true;
Type global{};
Type local{};
};
struct Values {
// Audio
std::string audio_device_id;
std::string sink_id;
bool audio_muted;
Setting<bool> enable_audio_stretching;
Setting<float> volume;
// Core
Setting<bool> use_multi_core;
// Cpu
CPUAccuracy cpu_accuracy;
bool cpuopt_page_tables;
bool cpuopt_block_linking;
bool cpuopt_return_stack_buffer;
bool cpuopt_fast_dispatcher;
bool cpuopt_context_elimination;
bool cpuopt_const_prop;
bool cpuopt_misc_ir;
bool cpuopt_reduce_misalign_checks;
// Renderer
Setting<RendererBackend> renderer_backend;
bool renderer_debug;
Setting<int> vulkan_device;
Setting<u16> resolution_factor = Setting(static_cast<u16>(1));
Setting<int> aspect_ratio;
Setting<int> max_anisotropy;
Setting<bool> use_frame_limit;
Setting<u16> frame_limit;
Setting<bool> use_disk_shader_cache;
Setting<GPUAccuracy> gpu_accuracy;
Setting<bool> use_asynchronous_gpu_emulation;
Setting<bool> use_vsync;
Setting<bool> use_assembly_shaders;
Setting<bool> force_30fps_mode;
Setting<bool> use_fast_gpu_time;
Setting<float> bg_red;
Setting<float> bg_green;
Setting<float> bg_blue;
// System
bool use_docked_mode;
std::optional<u32> rng_seed;
Setting<std::optional<u32>> rng_seed;
// Measured in seconds since epoch
std::optional<std::chrono::seconds> custom_rtc;
Setting<std::optional<std::chrono::seconds>> custom_rtc;
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
std::chrono::seconds custom_rtc_differential;
s32 current_user;
s32 language_index;
s32 region_index;
s32 time_zone_index;
s32 sound_index;
Setting<s32> language_index;
Setting<s32> region_index;
Setting<s32> time_zone_index;
Setting<s32> sound_index;
// Controls
std::array<PlayerInput, 10> players;
@ -419,51 +476,13 @@ struct Values {
u16 udp_input_port;
u8 udp_pad_index;
// Core
bool use_multi_core;
bool use_docked_mode;
// Data Storage
bool use_virtual_sd;
bool gamecard_inserted;
bool gamecard_current_game;
std::string gamecard_path;
NANDTotalSize nand_total_size;
NANDSystemSize nand_system_size;
NANDUserSize nand_user_size;
SDMCSize sdmc_size;
// Renderer
RendererBackend renderer_backend;
bool renderer_debug;
int vulkan_device;
u16 resolution_factor{1};
int aspect_ratio;
int max_anisotropy;
bool use_frame_limit;
u16 frame_limit;
bool use_disk_shader_cache;
GPUAccuracy gpu_accuracy;
bool use_asynchronous_gpu_emulation;
bool use_vsync;
bool use_assembly_shaders;
bool force_30fps_mode;
bool use_fast_gpu_time;
float bg_red;
float bg_green;
float bg_blue;
std::string log_filter;
bool use_dev_keys;
// Audio
bool audio_muted;
std::string sink_id;
bool enable_audio_stretching;
std::string audio_device_id;
float volume;
// Debugging
bool record_frame_times;
@ -474,10 +493,13 @@ struct Values {
bool dump_nso;
bool reporting_services;
bool quest_flag;
bool disable_cpu_opt;
bool disable_macro_jit;
// BCAT
// Misceallaneous
std::string log_filter;
bool use_dev_keys;
// Services
std::string bcat_backend;
bool bcat_boxcat_local;
@ -501,4 +523,7 @@ std::string GetTimeZoneString();
void Apply();
void LogSettings();
// Restore the global state of all applicable settings in the Values struct
void RestoreGlobalState();
} // namespace Settings

View File

@ -189,19 +189,24 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
// Log user configuration information
constexpr auto field_type = Telemetry::FieldType::UserConfig;
AddField(field_type, "Audio_SinkId", Settings::values.sink_id);
AddField(field_type, "Audio_EnableAudioStretching", Settings::values.enable_audio_stretching);
AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core);
AddField(field_type, "Renderer_Backend", TranslateRenderer(Settings::values.renderer_backend));
AddField(field_type, "Renderer_ResolutionFactor", Settings::values.resolution_factor);
AddField(field_type, "Renderer_UseFrameLimit", Settings::values.use_frame_limit);
AddField(field_type, "Renderer_FrameLimit", Settings::values.frame_limit);
AddField(field_type, "Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache);
AddField(field_type, "Audio_EnableAudioStretching",
Settings::values.enable_audio_stretching.GetValue());
AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
AddField(field_type, "Renderer_Backend",
TranslateRenderer(Settings::values.renderer_backend.GetValue()));
AddField(field_type, "Renderer_ResolutionFactor",
Settings::values.resolution_factor.GetValue());
AddField(field_type, "Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue());
AddField(field_type, "Renderer_FrameLimit", Settings::values.frame_limit.GetValue());
AddField(field_type, "Renderer_UseDiskShaderCache",
Settings::values.use_disk_shader_cache.GetValue());
AddField(field_type, "Renderer_GPUAccuracyLevel",
TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy));
TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue()));
AddField(field_type, "Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation);
AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync);
AddField(field_type, "Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders);
Settings::values.use_asynchronous_gpu_emulation.GetValue());
AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue());
AddField(field_type, "Renderer_UseAssemblyShaders",
Settings::values.use_assembly_shaders.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
}

View File

@ -30,7 +30,8 @@ if(SDL2_FOUND)
target_compile_definitions(input_common PRIVATE HAVE_SDL2)
endif()
target_link_libraries(input_common PUBLIC ${LIBUSB_LIBRARIES})
target_include_directories(input_common SYSTEM PRIVATE ${LIBUSB_INCLUDE_DIR})
target_link_libraries(input_common PRIVATE ${LIBUSB_LIBRARIES})
create_target_directory_groups(input_common)
target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost)

View File

@ -4,6 +4,7 @@
#include <chrono>
#include <thread>
#include <libusb.h>
#include "common/logging/log.h"
#include "input_common/gcadapter/gc_adapter.h"
@ -34,7 +35,7 @@ Adapter::Adapter() {
}
}
GCPadStatus Adapter::GetPadStatus(int port, const std::array<u8, 37>& adapter_payload) {
GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) {
GCPadStatus pad = {};
ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
@ -205,7 +206,7 @@ void Adapter::StartScanThread() {
}
detect_thread_running = true;
detect_thread = std::thread([=] { ScanThreadFunc(); });
detect_thread = std::thread(&Adapter::ScanThreadFunc, this);
}
void Adapter::StopScanThread() {
@ -234,7 +235,7 @@ void Adapter::Setup() {
}
if (devices != nullptr) {
for (std::size_t index = 0; index < device_count; ++index) {
for (std::size_t index = 0; index < static_cast<std::size_t>(device_count); ++index) {
if (CheckDeviceAccess(devices[index])) {
// GC Adapter found and accessible, registering it
GetGCEndpoint(devices[index]);
@ -368,11 +369,11 @@ void Adapter::Reset() {
}
}
bool Adapter::DeviceConnected(int port) {
bool Adapter::DeviceConnected(std::size_t port) {
return adapter_controllers_status[port] != ControllerTypes::None;
}
void Adapter::ResetDeviceType(int port) {
void Adapter::ResetDeviceType(std::size_t port) {
adapter_controllers_status[port] = ControllerTypes::None;
}

View File

@ -8,10 +8,13 @@
#include <mutex>
#include <thread>
#include <unordered_map>
#include <libusb.h>
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
struct libusb_context;
struct libusb_device;
struct libusb_device_handle;
namespace GCAdapter {
enum class PadButton {
@ -91,6 +94,9 @@ public:
void BeginConfiguration();
void EndConfiguration();
/// Returns true if there is a device connected to port
bool DeviceConnected(std::size_t port);
std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue();
const std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue() const;
@ -100,7 +106,7 @@ public:
int GetOriginValue(int port, int axis) const;
private:
GCPadStatus GetPadStatus(int port, const std::array<u8, 37>& adapter_payload);
GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
void PadToState(const GCPadStatus& pad, GCState& state);
@ -112,11 +118,8 @@ private:
/// Stop scanning for the adapter
void StopScanThread();
/// Returns true if there is a device connected to port
bool DeviceConnected(int port);
/// Resets status of device connected to port
void ResetDeviceType(int port);
void ResetDeviceType(std::size_t port);
/// Returns true if we successfully gain access to GC Adapter
bool CheckDeviceAccess(libusb_device* device);

View File

@ -6,6 +6,7 @@
#include <list>
#include <mutex>
#include <utility>
#include "common/assert.h"
#include "common/threadsafe_queue.h"
#include "input_common/gcadapter/gc_adapter.h"
#include "input_common/gcadapter/gc_poller.h"
@ -20,7 +21,10 @@ public:
~GCButton() override;
bool GetStatus() const override {
return gcadapter->GetPadState()[port].buttons.at(button);
if (gcadapter->DeviceConnected(port)) {
return gcadapter->GetPadState()[port].buttons.at(button);
}
return false;
}
private:
@ -37,14 +41,17 @@ public:
gcadapter(adapter), origin_value(adapter->GetOriginValue(port_, axis_)) {}
bool GetStatus() const override {
const float current_axis_value = gcadapter->GetPadState()[port].axes.at(axis);
const float axis_value = (current_axis_value - origin_value) / 128.0f;
if (trigger_if_greater) {
// TODO: Might be worthwile to set a slider for the trigger threshold. It is currently
// always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
return axis_value > threshold;
if (gcadapter->DeviceConnected(port)) {
const float current_axis_value = gcadapter->GetPadState()[port].axes.at(axis);
const float axis_value = (current_axis_value - origin_value) / 128.0f;
if (trigger_if_greater) {
// TODO: Might be worthwile to set a slider for the trigger threshold. It is
// currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
return axis_value > threshold;
}
return axis_value < -threshold;
}
return axis_value < -threshold;
return false;
}
private:
@ -90,9 +97,12 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
return std::make_unique<GCAxisButton>(port, axis, threshold, trigger_if_greater,
adapter.get());
}
UNREACHABLE();
return nullptr;
}
Common::ParamPackage GCButtonFactory::GetNextInput() {
Common::ParamPackage GCButtonFactory::GetNextInput() const {
Common::ParamPackage params;
GCAdapter::GCPadStatus pad;
auto& queue = adapter->GetPadQueue();
@ -145,12 +155,15 @@ public:
origin_value_y(adapter->GetOriginValue(port_, axis_y_)) {}
float GetAxis(int axis) const {
std::lock_guard lock{mutex};
const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
// division is not by a perfect 128 to account for some variance in center location
// e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
// [20-230]
return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f;
if (gcadapter->DeviceConnected(port)) {
std::lock_guard lock{mutex};
const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
// division is not by a perfect 128 to account for some variance in center location
// e.g. my device idled at 131 in X, 120 in Y, and full range of motion was in range
// [20-230]
return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / 95.0f;
}
return 0.0f;
}
std::pair<float, float> GetAnalog(int axis_x, int axis_y) const {
@ -250,7 +263,7 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
const u8 axis = static_cast<u8>(pad.axis);
if (analog_x_axis == -1) {
analog_x_axis = axis;
controller_number = port;
controller_number = static_cast<int>(port);
} else if (analog_y_axis == -1 && analog_x_axis != axis && controller_number == port) {
analog_y_axis = axis;
}

View File

@ -25,7 +25,7 @@ public:
*/
std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput();
Common::ParamPackage GetNextInput() const;
/// For device input configuration/polling
void BeginConfiguration();

View File

@ -4,7 +4,6 @@
#include <memory>
#include <thread>
#include <libusb.h>
#include "common/param_package.h"
#include "input_common/analog_from_button.h"
#include "input_common/gcadapter/gc_adapter.h"

View File

@ -234,7 +234,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=] {
std::thread([=, this] {
constexpr u16 CALIBRATION_THRESHOLD = 100;
u16 min_x{UINT16_MAX};

View File

@ -96,7 +96,8 @@ public:
}
if (is_written) {
map->MarkAsModified(true, GetModifiedTicks());
if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) {
if (Settings::IsGPULevelHigh() &&
Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
MarkForAsyncFlush(map);
}
if (!map->is_written) {
@ -369,7 +370,8 @@ private:
}
if (modified_inheritance) {
map->MarkAsModified(true, GetModifiedTicks());
if (Settings::IsGPULevelHigh() && Settings::values.use_asynchronous_gpu_emulation) {
if (Settings::IsGPULevelHigh() &&
Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
MarkForAsyncFlush(map);
}
}

View File

@ -157,7 +157,7 @@ u64 GPU::GetTicks() const {
constexpr u64 gpu_ticks_den = 625;
u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count();
if (Settings::values.use_fast_gpu_time) {
if (Settings::values.use_fast_gpu_time.GetValue()) {
nanoseconds /= 256;
}
const u64 nanoseconds_num = nanoseconds / gpu_ticks_den;

View File

@ -132,7 +132,7 @@ public:
}
query->BindCounter(Stream(type).Current(), timestamp);
if (Settings::values.use_asynchronous_gpu_emulation) {
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
AsyncFlushQuery(cpu_addr);
}
}

View File

@ -18,7 +18,7 @@ RendererBase::~RendererBase() = default;
void RendererBase::RefreshBaseSettings() {
UpdateCurrentFramebufferLayout();
renderer_settings.use_framelimiter = Settings::values.use_frame_limit;
renderer_settings.use_framelimiter = Settings::values.use_frame_limit.GetValue();
renderer_settings.set_background_color = true;
}

View File

@ -229,15 +229,15 @@ Device::Device()
// uniform buffers as "push constants"
has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data;
use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 &&
GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback &&
GLAD_GL_NV_transform_feedback2;
use_assembly_shaders = Settings::values.use_assembly_shaders.GetValue() &&
GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 &&
GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2;
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug);
if (Settings::values.use_assembly_shaders && !use_assembly_shaders) {
if (Settings::values.use_assembly_shaders.GetValue() && !use_assembly_shaders) {
LOG_ERROR(Render_OpenGL, "Assembly shaders enabled but not supported");
}
}

View File

@ -213,7 +213,7 @@ ShaderDiskCacheOpenGL::~ShaderDiskCacheOpenGL() = default;
std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTransferable() {
// Skip games without title id
const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0;
if (!Settings::values.use_disk_shader_cache || !has_title_id) {
if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) {
return {};
}

View File

@ -455,8 +455,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
void RendererOpenGL::InitOpenGLObjects() {
frame_mailbox = std::make_unique<FrameMailbox>();
glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
0.0f);
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
Settings::values.bg_blue.GetValue(), 0.0f);
// Create shader programs
OGLShader vertex_shader;
@ -561,8 +561,8 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
if (renderer_settings.set_background_color) {
// Update background color before drawing
glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
0.0f);
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
Settings::values.bg_blue.GetValue(), 0.0f);
}
// Set projection matrix

View File

@ -409,7 +409,7 @@ bool RendererVulkan::PickDevices() {
return false;
}
const s32 device_index = Settings::values.vulkan_device;
const s32 device_index = Settings::values.vulkan_device.GetValue();
if (device_index < 0 || device_index >= static_cast<s32>(devices->size())) {
LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
return false;

View File

@ -332,23 +332,23 @@ private:
if constexpr (has_extended_dynamic_state) {
// With extended dynamic states we can specify the length and stride of a vertex buffer
// std::array<VkDeviceSize, N> sizes;
std::array<VkDeviceSize, N> sizes;
std::array<u16, N> strides;
// std::copy(vertex.sizes.begin(), vertex.sizes.begin() + N, sizes.begin());
std::copy(vertex.sizes.begin(), vertex.sizes.begin() + N, sizes.begin());
std::copy(vertex.strides.begin(), vertex.strides.begin() + N, strides.begin());
if constexpr (is_indexed) {
scheduler.Record(
[buffers, offsets, strides, index = index](vk::CommandBuffer cmdbuf) {
[buffers, offsets, sizes, strides, index = index](vk::CommandBuffer cmdbuf) {
cmdbuf.BindIndexBuffer(index.buffer, index.offset, index.type);
cmdbuf.BindVertexBuffers2EXT(0, static_cast<u32>(N), buffers.data(),
offsets.data(), nullptr,
offsets.data(), sizes.data(),
ExpandStrides(strides).data());
});
} else {
scheduler.Record([buffers, offsets, strides](vk::CommandBuffer cmdbuf) {
scheduler.Record([buffers, offsets, sizes, strides](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers2EXT(0, static_cast<u32>(N), buffers.data(),
offsets.data(), nullptr,
offsets.data(), sizes.data(),
ExpandStrides(strides).data());
});
}

View File

@ -121,7 +121,7 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) {
// Substract from the preferred heap size some bytes to avoid getting out of memory.
const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size;
const VkDeviceSize allocable_size = heap_size - 4 * 1024 * 1024;
const VkDeviceSize allocable_size = heap_size - 9 * 1024 * 1024;
VkBufferCreateInfo buffer_ci;
buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;

View File

@ -249,7 +249,7 @@ public:
auto& surface = render_targets[index].target;
surface->MarkAsRenderTarget(false, NO_RT);
const auto& cr_params = surface->GetSurfaceParams();
if (!cr_params.is_tiled && Settings::values.use_asynchronous_gpu_emulation) {
if (!cr_params.is_tiled && Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
AsyncFlushSurface(surface);
}
}

View File

@ -48,7 +48,7 @@ constexpr std::array<float, 256> SRGB_CONVERSION_LUT = {
};
unsigned SettingsMinimumAnisotropy() noexcept {
switch (static_cast<Anisotropy>(Settings::values.max_anisotropy)) {
switch (static_cast<Anisotropy>(Settings::values.max_anisotropy.GetValue())) {
default:
case Anisotropy::Default:
return 1U;

View File

@ -19,7 +19,7 @@ namespace {
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
Core::System& system,
Core::Frontend::GraphicsContext& context) {
switch (Settings::values.renderer_backend) {
switch (Settings::values.renderer_backend.GetValue()) {
case Settings::RendererBackend::OpenGL:
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context);
#ifdef HAS_VULKAN
@ -42,7 +42,7 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor
return nullptr;
}
if (Settings::values.use_asynchronous_gpu_emulation) {
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer),
std::move(context));
}
@ -51,8 +51,8 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Cor
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
return static_cast<u16>(
Settings::values.resolution_factor != 0
? Settings::values.resolution_factor
Settings::values.resolution_factor.GetValue() != 0
? Settings::values.resolution_factor.GetValue()
: renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio());
}

View File

@ -24,10 +24,18 @@ add_executable(yuzu
compatibility_list.h
configuration/config.cpp
configuration/config.h
configuration/configuration_shared.cpp
configuration/configuration_shared.h
configuration/configure.ui
configuration/configure_audio.cpp
configuration/configure_audio.h
configuration/configure_audio.ui
configuration/configure_cpu.cpp
configuration/configure_cpu.h
configuration/configure_cpu.ui
configuration/configure_cpu_debug.cpp
configuration/configure_cpu_debug.h
configuration/configure_cpu_debug.ui
configuration/configure_debug.cpp
configuration/configure_debug.h
configuration/configure_debug.ui
@ -60,9 +68,12 @@ add_executable(yuzu
configuration/configure_mouse_advanced.cpp
configuration/configure_mouse_advanced.h
configuration/configure_mouse_advanced.ui
configuration/configure_per_general.cpp
configuration/configure_per_general.h
configuration/configure_per_general.ui
configuration/configure_per_game.cpp
configuration/configure_per_game.h
configuration/configure_per_game.ui
configuration/configure_per_game_addons.cpp
configuration/configure_per_game_addons.h
configuration/configure_per_game_addons.ui
configuration/configure_profile_manager.cpp
configuration/configure_profile_manager.h
configuration/configure_profile_manager.ui
@ -93,11 +104,13 @@ add_executable(yuzu
game_list_p.h
game_list_worker.cpp
game_list_worker.h
hotkeys.cpp
hotkeys.h
install_dialog.cpp
install_dialog.h
loading_screen.cpp
loading_screen.h
loading_screen.ui
hotkeys.cpp
hotkeys.h
main.cpp
main.h
main.ui
@ -147,7 +160,7 @@ endif()
create_target_directory_groups(yuzu)
target_link_libraries(yuzu PRIVATE common core input_common video_core)
target_link_libraries(yuzu PRIVATE Boost::boost glad Qt5::OpenGL Qt5::Widgets)
target_link_libraries(yuzu PRIVATE Boost::boost glad Qt5::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
if (ENABLE_VULKAN AND NOT WIN32)

View File

@ -145,7 +145,7 @@ public:
// disable vsync for any shared contexts
auto format = share_context->format();
format.setSwapInterval(main_surface ? Settings::values.use_vsync : 0);
format.setSwapInterval(main_surface ? Settings::values.use_vsync.GetValue() : 0);
context = std::make_unique<QOpenGLContext>();
context->setShareContext(share_context);
@ -495,7 +495,7 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) {
std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
#ifdef HAS_OPENGL
if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) {
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL) {
auto c = static_cast<OpenGLSharedContext*>(main_context.get());
// Bind the shared contexts to the main surface in case the backend wants to take over
// presentation
@ -511,7 +511,7 @@ bool GRenderWindow::InitRenderTarget() {
first_frame = false;
switch (Settings::values.renderer_backend) {
switch (Settings::values.renderer_backend.GetValue()) {
case Settings::RendererBackend::OpenGL:
if (!InitializeOpenGL()) {
return false;
@ -538,7 +538,7 @@ bool GRenderWindow::InitRenderTarget() {
OnFramebufferSizeChanged();
BackupGeometry();
if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) {
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL) {
if (!LoadOpenGL()) {
return false;
}

View File

@ -13,17 +13,20 @@
#include "input_common/udp/client.h"
#include "yuzu/configuration/config.h"
Config::Config() {
Config::Config(const std::string& config_file, bool is_global) {
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "qt-config.ini";
qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + config_file;
FileUtil::CreateFullPath(qt_config_loc);
qt_config =
std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
global = is_global;
Reload();
}
Config::~Config() {
Save();
if (global) {
Save();
}
}
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
@ -402,16 +405,19 @@ void Config::ApplyDefaultProfileIfInputInvalid() {
void Config::ReadAudioValues() {
qt_config->beginGroup(QStringLiteral("Audio"));
Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto"))
.toString()
.toStdString();
Settings::values.enable_audio_stretching =
ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool();
Settings::values.audio_device_id =
ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto"))
.toString()
.toStdString();
Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat();
if (global) {
Settings::values.sink_id =
ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto"))
.toString()
.toStdString();
Settings::values.audio_device_id =
ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto"))
.toString()
.toStdString();
}
ReadSettingGlobal(Settings::values.enable_audio_stretching,
QStringLiteral("enable_audio_stretching"), true);
ReadSettingGlobal(Settings::values.volume, QStringLiteral("volume"), 1);
qt_config->endGroup();
}
@ -440,6 +446,8 @@ void Config::ReadControlValues() {
.toInt());
Settings::values.udp_pad_index =
static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt());
Settings::values.use_docked_mode =
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
qt_config->endGroup();
}
@ -447,7 +455,7 @@ void Config::ReadControlValues() {
void Config::ReadCoreValues() {
qt_config->beginGroup(QStringLiteral("Core"));
Settings::values.use_multi_core = ReadSetting(QStringLiteral("use_multi_core"), false).toBool();
ReadSettingGlobal(Settings::values.use_multi_core, QStringLiteral("use_multi_core"), false);
qt_config->endGroup();
}
@ -497,22 +505,6 @@ void Config::ReadDataStorageValues() {
ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool();
Settings::values.gamecard_path =
ReadSetting(QStringLiteral("gamecard_path"), QStringLiteral("")).toString().toStdString();
Settings::values.nand_total_size = static_cast<Settings::NANDTotalSize>(
ReadSetting(QStringLiteral("nand_total_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDTotalSize::S29_1GB)))
.toULongLong());
Settings::values.nand_user_size = static_cast<Settings::NANDUserSize>(
ReadSetting(QStringLiteral("nand_user_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDUserSize::S26GB)))
.toULongLong());
Settings::values.nand_system_size = static_cast<Settings::NANDSystemSize>(
ReadSetting(QStringLiteral("nand_system_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDSystemSize::S2_5GB)))
.toULongLong());
Settings::values.sdmc_size = static_cast<Settings::SDMCSize>(
ReadSetting(QStringLiteral("sdmc_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::SDMCSize::S16GB)))
.toULongLong());
qt_config->endGroup();
}
@ -532,8 +524,6 @@ void Config::ReadDebuggingValues() {
Settings::values.reporting_services =
ReadSetting(QStringLiteral("reporting_services"), false).toBool();
Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), false).toBool();
Settings::values.disable_cpu_opt =
ReadSetting(QStringLiteral("disable_cpu_opt"), false).toBool();
Settings::values.disable_macro_jit =
ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool();
@ -625,35 +615,59 @@ void Config::ReadPathValues() {
qt_config->endGroup();
}
void Config::ReadCpuValues() {
qt_config->beginGroup(QStringLiteral("Cpu"));
if (global) {
Settings::values.cpu_accuracy = static_cast<Settings::CPUAccuracy>(
ReadSetting(QStringLiteral("cpu_accuracy"), 0).toInt());
Settings::values.cpuopt_page_tables =
ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool();
Settings::values.cpuopt_block_linking =
ReadSetting(QStringLiteral("cpuopt_block_linking"), true).toBool();
Settings::values.cpuopt_return_stack_buffer =
ReadSetting(QStringLiteral("cpuopt_return_stack_buffer"), true).toBool();
Settings::values.cpuopt_fast_dispatcher =
ReadSetting(QStringLiteral("cpuopt_fast_dispatcher"), true).toBool();
Settings::values.cpuopt_context_elimination =
ReadSetting(QStringLiteral("cpuopt_context_elimination"), true).toBool();
Settings::values.cpuopt_const_prop =
ReadSetting(QStringLiteral("cpuopt_const_prop"), true).toBool();
Settings::values.cpuopt_misc_ir =
ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool();
Settings::values.cpuopt_reduce_misalign_checks =
ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool();
}
qt_config->endGroup();
}
void Config::ReadRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer"));
Settings::values.renderer_backend =
static_cast<Settings::RendererBackend>(ReadSetting(QStringLiteral("backend"), 0).toInt());
Settings::values.renderer_debug = ReadSetting(QStringLiteral("debug"), false).toBool();
Settings::values.vulkan_device = ReadSetting(QStringLiteral("vulkan_device"), 0).toInt();
Settings::values.aspect_ratio = ReadSetting(QStringLiteral("aspect_ratio"), 0).toInt();
Settings::values.max_anisotropy = ReadSetting(QStringLiteral("max_anisotropy"), 0).toInt();
Settings::values.use_frame_limit =
ReadSetting(QStringLiteral("use_frame_limit"), true).toBool();
Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toUInt();
Settings::values.use_disk_shader_cache =
ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool();
const int gpu_accuracy_level = ReadSetting(QStringLiteral("gpu_accuracy"), 0).toInt();
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(gpu_accuracy_level);
Settings::values.use_asynchronous_gpu_emulation =
ReadSetting(QStringLiteral("use_asynchronous_gpu_emulation"), false).toBool();
Settings::values.use_vsync = ReadSetting(QStringLiteral("use_vsync"), true).toBool();
Settings::values.use_assembly_shaders =
ReadSetting(QStringLiteral("use_assembly_shaders"), false).toBool();
Settings::values.use_fast_gpu_time =
ReadSetting(QStringLiteral("use_fast_gpu_time"), true).toBool();
Settings::values.force_30fps_mode =
ReadSetting(QStringLiteral("force_30fps_mode"), false).toBool();
ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0);
ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false);
ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0);
ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0);
ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0);
ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true);
ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100);
ReadSettingGlobal(Settings::values.use_disk_shader_cache,
QStringLiteral("use_disk_shader_cache"), true);
ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 0);
ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation,
QStringLiteral("use_asynchronous_gpu_emulation"), false);
ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true);
ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"),
false);
ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
true);
ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false);
Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat();
Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat();
Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat();
ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0);
ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0);
ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0);
qt_config->endGroup();
}
@ -682,35 +696,45 @@ void Config::ReadShortcutValues() {
void Config::ReadSystemValues() {
qt_config->beginGroup(QStringLiteral("System"));
Settings::values.use_docked_mode =
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
ReadSettingGlobal(Settings::values.current_user, QStringLiteral("current_user"), 0);
Settings::values.current_user =
std::clamp<int>(Settings::values.current_user, 0, Service::Account::MAX_USERS - 1);
Settings::values.current_user = std::clamp<int>(
ReadSetting(QStringLiteral("current_user"), 0).toInt(), 0, Service::Account::MAX_USERS - 1);
ReadSettingGlobal(Settings::values.language_index, QStringLiteral("language_index"), 1);
Settings::values.language_index = ReadSetting(QStringLiteral("language_index"), 1).toInt();
ReadSettingGlobal(Settings::values.region_index, QStringLiteral("region_index"), 1);
Settings::values.region_index = ReadSetting(QStringLiteral("region_index"), 1).toInt();
ReadSettingGlobal(Settings::values.time_zone_index, QStringLiteral("time_zone_index"), 0);
Settings::values.time_zone_index = ReadSetting(QStringLiteral("time_zone_index"), 0).toInt();
const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool();
if (rng_seed_enabled) {
Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong();
} else {
Settings::values.rng_seed = std::nullopt;
bool rng_seed_enabled;
ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false);
bool rng_seed_global =
global || qt_config->value(QStringLiteral("rng_seed/use_global"), true).toBool();
Settings::values.rng_seed.SetGlobal(rng_seed_global);
if (global || !rng_seed_global) {
if (rng_seed_enabled) {
Settings::values.rng_seed.SetValue(
ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong());
} else {
Settings::values.rng_seed.SetValue(std::nullopt);
}
}
const auto custom_rtc_enabled =
ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool();
if (custom_rtc_enabled) {
Settings::values.custom_rtc =
std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong());
} else {
Settings::values.custom_rtc = std::nullopt;
bool custom_rtc_enabled;
ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false);
bool custom_rtc_global =
global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool();
Settings::values.custom_rtc.SetGlobal(custom_rtc_global);
if (global || !custom_rtc_global) {
if (custom_rtc_enabled) {
Settings::values.custom_rtc.SetValue(
std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()));
} else {
Settings::values.custom_rtc.SetValue(std::nullopt);
}
}
Settings::values.sound_index = ReadSetting(QStringLiteral("sound_index"), 1).toInt();
ReadSettingGlobal(Settings::values.sound_index, QStringLiteral("sound_index"), 1);
qt_config->endGroup();
}
@ -804,18 +828,21 @@ void Config::ReadWebServiceValues() {
}
void Config::ReadValues() {
ReadControlValues();
if (global) {
ReadControlValues();
ReadDataStorageValues();
ReadDebuggingValues();
ReadDisabledAddOnValues();
ReadServiceValues();
ReadUIValues();
ReadWebServiceValues();
ReadMiscellaneousValues();
}
ReadCoreValues();
ReadCpuValues();
ReadRendererValues();
ReadAudioValues();
ReadDataStorageValues();
ReadSystemValues();
ReadMiscellaneousValues();
ReadDebuggingValues();
ReadWebServiceValues();
ReadServiceValues();
ReadDisabledAddOnValues();
ReadUIValues();
}
void Config::SavePlayerValues() {
@ -902,30 +929,36 @@ void Config::SaveTouchscreenValues() {
}
void Config::SaveValues() {
SaveControlValues();
if (global) {
SaveControlValues();
SaveDataStorageValues();
SaveDebuggingValues();
SaveDisabledAddOnValues();
SaveServiceValues();
SaveUIValues();
SaveWebServiceValues();
SaveMiscellaneousValues();
}
SaveCoreValues();
SaveCpuValues();
SaveRendererValues();
SaveAudioValues();
SaveDataStorageValues();
SaveSystemValues();
SaveMiscellaneousValues();
SaveDebuggingValues();
SaveWebServiceValues();
SaveServiceValues();
SaveDisabledAddOnValues();
SaveUIValues();
}
void Config::SaveAudioValues() {
qt_config->beginGroup(QStringLiteral("Audio"));
WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id),
QStringLiteral("auto"));
WriteSetting(QStringLiteral("enable_audio_stretching"),
Settings::values.enable_audio_stretching, true);
WriteSetting(QStringLiteral("output_device"),
QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto"));
WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f);
if (global) {
WriteSetting(QStringLiteral("output_engine"),
QString::fromStdString(Settings::values.sink_id), QStringLiteral("auto"));
WriteSetting(QStringLiteral("output_device"),
QString::fromStdString(Settings::values.audio_device_id),
QStringLiteral("auto"));
}
WriteSettingGlobal(QStringLiteral("enable_audio_stretching"),
Settings::values.enable_audio_stretching, true);
WriteSettingGlobal(QStringLiteral("volume"), Settings::values.volume, 1.0f);
qt_config->endGroup();
}
@ -948,6 +981,7 @@ void Config::SaveControlValues() {
WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port,
InputCommon::CemuhookUDP::DEFAULT_PORT);
WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0);
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
qt_config->endGroup();
}
@ -955,7 +989,7 @@ void Config::SaveControlValues() {
void Config::SaveCoreValues() {
qt_config->beginGroup(QStringLiteral("Core"));
WriteSetting(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false);
WriteSettingGlobal(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false);
qt_config->endGroup();
}
@ -984,18 +1018,7 @@ void Config::SaveDataStorageValues() {
false);
WriteSetting(QStringLiteral("gamecard_path"),
QString::fromStdString(Settings::values.gamecard_path), QStringLiteral(""));
WriteSetting(QStringLiteral("nand_total_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::values.nand_total_size)),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDTotalSize::S29_1GB)));
WriteSetting(QStringLiteral("nand_user_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::values.nand_user_size)),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDUserSize::S26GB)));
WriteSetting(QStringLiteral("nand_system_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::values.nand_system_size)),
QVariant::fromValue<u64>(static_cast<u64>(Settings::NANDSystemSize::S2_5GB)));
WriteSetting(QStringLiteral("sdmc_size"),
QVariant::fromValue<u64>(static_cast<u64>(Settings::values.sdmc_size)),
QVariant::fromValue<u64>(static_cast<u64>(Settings::SDMCSize::S16GB)));
qt_config->endGroup();
}
@ -1011,7 +1034,6 @@ void Config::SaveDebuggingValues() {
WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false);
WriteSetting(QStringLiteral("disable_cpu_opt"), Settings::values.disable_cpu_opt, false);
WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false);
qt_config->endGroup();
@ -1075,32 +1097,63 @@ void Config::SavePathValues() {
qt_config->endGroup();
}
void Config::SaveCpuValues() {
qt_config->beginGroup(QStringLiteral("Cpu"));
if (global) {
WriteSetting(QStringLiteral("cpu_accuracy"),
static_cast<int>(Settings::values.cpu_accuracy), 0);
WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables,
true);
WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking,
true);
WriteSetting(QStringLiteral("cpuopt_return_stack_buffer"),
Settings::values.cpuopt_return_stack_buffer, true);
WriteSetting(QStringLiteral("cpuopt_fast_dispatcher"),
Settings::values.cpuopt_fast_dispatcher, true);
WriteSetting(QStringLiteral("cpuopt_context_elimination"),
Settings::values.cpuopt_context_elimination, true);
WriteSetting(QStringLiteral("cpuopt_const_prop"), Settings::values.cpuopt_const_prop, true);
WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true);
WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"),
Settings::values.cpuopt_reduce_misalign_checks, true);
}
qt_config->endGroup();
}
void Config::SaveRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer"));
WriteSetting(QStringLiteral("backend"), static_cast<int>(Settings::values.renderer_backend), 0);
WriteSettingGlobal(QStringLiteral("backend"),
static_cast<int>(Settings::values.renderer_backend.GetValue(global)),
Settings::values.renderer_backend.UsingGlobal(), 0);
WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false);
WriteSetting(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0);
WriteSetting(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0);
WriteSetting(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0);
WriteSetting(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true);
WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100);
WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache,
true);
WriteSetting(QStringLiteral("gpu_accuracy"), static_cast<int>(Settings::values.gpu_accuracy),
0);
WriteSetting(QStringLiteral("use_asynchronous_gpu_emulation"),
Settings::values.use_asynchronous_gpu_emulation, false);
WriteSetting(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
WriteSetting(QStringLiteral("use_assembly_shaders"), Settings::values.use_assembly_shaders,
false);
WriteSetting(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, true);
WriteSetting(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, false);
WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0);
WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0);
WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0);
WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true);
WriteSettingGlobal(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100);
WriteSettingGlobal(QStringLiteral("use_disk_shader_cache"),
Settings::values.use_disk_shader_cache, true);
WriteSettingGlobal(QStringLiteral("gpu_accuracy"),
static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)),
Settings::values.gpu_accuracy.UsingGlobal(), 0);
WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"),
Settings::values.use_asynchronous_gpu_emulation, false);
WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
WriteSettingGlobal(QStringLiteral("use_assembly_shaders"),
Settings::values.use_assembly_shaders, false);
WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time,
true);
WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode,
false);
// Cast to double because Qt's written float values are not human-readable
WriteSetting(QStringLiteral("bg_red"), static_cast<double>(Settings::values.bg_red), 0.0);
WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0);
WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0);
WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0);
WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0);
WriteSettingGlobal(QStringLiteral("bg_blue"), Settings::values.bg_blue, 0.0);
qt_config->endGroup();
}
@ -1128,23 +1181,28 @@ void Config::SaveShortcutValues() {
void Config::SaveSystemValues() {
qt_config->beginGroup(QStringLiteral("System"));
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0);
WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1);
WriteSetting(QStringLiteral("region_index"), Settings::values.region_index, 1);
WriteSetting(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0);
WriteSettingGlobal(QStringLiteral("language_index"), Settings::values.language_index, 1);
WriteSettingGlobal(QStringLiteral("region_index"), Settings::values.region_index, 1);
WriteSettingGlobal(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0);
WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false);
WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0);
WriteSettingGlobal(QStringLiteral("rng_seed_enabled"),
Settings::values.rng_seed.GetValue(global).has_value(),
Settings::values.rng_seed.UsingGlobal(), false);
WriteSettingGlobal(QStringLiteral("rng_seed"),
Settings::values.rng_seed.GetValue(global).value_or(0),
Settings::values.rng_seed.UsingGlobal(), 0);
WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(),
false);
WriteSetting(QStringLiteral("custom_rtc"),
QVariant::fromValue<long long>(
Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
0);
WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"),
Settings::values.custom_rtc.GetValue(global).has_value(),
Settings::values.custom_rtc.UsingGlobal(), false);
WriteSettingGlobal(
QStringLiteral("custom_rtc"),
QVariant::fromValue<long long>(
Settings::values.custom_rtc.GetValue(global).value_or(std::chrono::seconds{}).count()),
Settings::values.custom_rtc.UsingGlobal(), 0);
WriteSetting(QStringLiteral("sound_index"), Settings::values.sound_index, 1);
WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1);
qt_config->endGroup();
}
@ -1236,6 +1294,34 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value)
return result;
}
template <typename Type>
void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name) {
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
setting.SetGlobal(use_global);
if (global || !use_global) {
setting.SetValue(ReadSetting(name).value<Type>());
}
}
template <typename Type>
void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name,
const QVariant& default_value) {
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
setting.SetGlobal(use_global);
if (global || !use_global) {
setting.SetValue(ReadSetting(name, default_value).value<Type>());
}
}
template <typename Type>
void Config::ReadSettingGlobal(Type& setting, const QString& name,
const QVariant& default_value) const {
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
if (global || !use_global) {
setting = ReadSetting(name, default_value).value<Type>();
}
}
void Config::WriteSetting(const QString& name, const QVariant& value) {
qt_config->setValue(name, value);
}
@ -1246,6 +1332,40 @@ void Config::WriteSetting(const QString& name, const QVariant& value,
qt_config->setValue(name, value);
}
template <typename Type>
void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting) {
if (!global) {
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
}
if (global || !setting.UsingGlobal()) {
qt_config->setValue(name, setting.GetValue(global));
}
}
template <typename Type>
void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting,
const QVariant& default_value) {
if (!global) {
qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
}
if (global || !setting.UsingGlobal()) {
qt_config->setValue(name + QStringLiteral("/default"),
setting.GetValue(global) == default_value.value<Type>());
qt_config->setValue(name, setting.GetValue(global));
}
}
void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global,
const QVariant& default_value) {
if (!global) {
qt_config->setValue(name + QStringLiteral("/use_global"), use_global);
}
if (global || !use_global) {
qt_config->setValue(name + QStringLiteral("/default"), value == default_value);
qt_config->setValue(name, value);
}
}
void Config::Reload() {
ReadValues();
// To apply default value changes

View File

@ -7,6 +7,7 @@
#include <array>
#include <memory>
#include <string>
#include <QMetaType>
#include <QVariant>
#include "core/settings.h"
#include "yuzu/uisettings.h"
@ -15,7 +16,7 @@ class QSettings;
class Config {
public:
Config();
explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true);
~Config();
void Reload();
@ -48,6 +49,7 @@ private:
void ReadDisabledAddOnValues();
void ReadMiscellaneousValues();
void ReadPathValues();
void ReadCpuValues();
void ReadRendererValues();
void ReadShortcutValues();
void ReadSystemValues();
@ -72,6 +74,7 @@ private:
void SaveDisabledAddOnValues();
void SaveMiscellaneousValues();
void SavePathValues();
void SaveCpuValues();
void SaveRendererValues();
void SaveShortcutValues();
void SaveSystemValues();
@ -82,9 +85,33 @@ private:
QVariant ReadSetting(const QString& name) const;
QVariant ReadSetting(const QString& name, const QVariant& default_value) const;
// Templated ReadSettingGlobal functions will also look for the use_global setting and set
// both the value and the global state properly
template <typename Type>
void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name);
template <typename Type>
void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name,
const QVariant& default_value);
template <typename Type>
void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const;
// Templated WriteSettingGlobal functions will also write the global state if needed and will
// skip writing the actual setting if it defers to the global value
void WriteSetting(const QString& name, const QVariant& value);
void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value);
template <typename Type>
void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting);
template <typename Type>
void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting,
const QVariant& default_value);
void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global,
const QVariant& default_value);
std::unique_ptr<QSettings> qt_config;
std::string qt_config_loc;
bool global;
};
// These metatype declarations cannot be in core/settings.h because core is devoid of QT
Q_DECLARE_METATYPE(Settings::RendererBackend);
Q_DECLARE_METATYPE(Settings::GPUAccuracy);

View File

@ -0,0 +1,76 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QCheckBox>
#include <QComboBox>
#include "core/settings.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_per_game.h"
void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting,
const QCheckBox* checkbox) {
if (checkbox->checkState() == Qt::PartiallyChecked) {
setting->SetGlobal(true);
} else {
setting->SetGlobal(false);
setting->SetValue(checkbox->checkState() == Qt::Checked);
}
}
void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting,
const QComboBox* combobox) {
if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
setting->SetGlobal(true);
} else {
setting->SetGlobal(false);
setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET);
}
}
void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
const QComboBox* combobox) {
if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
setting->SetGlobal(true);
} else {
setting->SetGlobal(false);
setting->SetValue(static_cast<Settings::RendererBackend>(
combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET));
}
}
void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox,
const Settings::Setting<bool>* setting) {
if (setting->UsingGlobal()) {
checkbox->setCheckState(Qt::PartiallyChecked);
} else {
checkbox->setCheckState(setting->GetValue() ? Qt::Checked : Qt::Unchecked);
}
}
void ConfigurationShared::SetPerGameSetting(QComboBox* combobox,
const Settings::Setting<int>* setting) {
combobox->setCurrentIndex(setting->UsingGlobal()
? ConfigurationShared::USE_GLOBAL_INDEX
: setting->GetValue() + ConfigurationShared::USE_GLOBAL_OFFSET);
}
void ConfigurationShared::SetPerGameSetting(
QComboBox* combobox, const Settings::Setting<Settings::RendererBackend>* setting) {
combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
: static_cast<int>(setting->GetValue()) +
ConfigurationShared::USE_GLOBAL_OFFSET);
}
void ConfigurationShared::SetPerGameSetting(
QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting) {
combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
: static_cast<int>(setting->GetValue()) +
ConfigurationShared::USE_GLOBAL_OFFSET);
}
void ConfigurationShared::InsertGlobalItem(QComboBox* combobox) {
const QString use_global_text = ConfigurePerGame::tr("Use global configuration");
combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
}

View File

@ -0,0 +1,36 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <QCheckBox>
#include <QComboBox>
#include <QString>
#include "core/settings.h"
namespace ConfigurationShared {
constexpr int USE_GLOBAL_INDEX = 0;
constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1;
constexpr int USE_GLOBAL_OFFSET = 2;
// Global-aware apply and set functions
void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox);
void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox);
void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
const QComboBox* combobox);
void ApplyPerGameSetting(Settings::Setting<Settings::GPUAccuracy>* setting,
const QComboBox* combobox);
void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting);
void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting);
void SetPerGameSetting(QComboBox* combobox,
const Settings::Setting<Settings::RendererBackend>* setting);
void SetPerGameSetting(QComboBox* combobox,
const Settings::Setting<Settings::GPUAccuracy>* setting);
void InsertGlobalItem(QComboBox* combobox);
} // namespace ConfigurationShared

View File

@ -78,6 +78,16 @@
<string>Hotkeys</string>
</attribute>
</widget>
<widget class="ConfigureCpu" name="cpuTab">
<attribute name="title">
<string>CPU</string>
</attribute>
</widget>
<widget class="ConfigureCpuDebug" name="cpuDebugTab">
<attribute name="title">
<string>Debug</string>
</attribute>
</widget>
<widget class="ConfigureGraphics" name="graphicsTab">
<attribute name="title">
<string>Graphics</string>
@ -158,6 +168,18 @@
<header>configuration/configure_debug.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureCpu</class>
<extends>QWidget</extends>
<header>configuration/configure_cpu.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureCpuDebug</class>
<extends>QWidget</extends>
<header>configuration/configure_cpu_debug.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGraphics</class>
<extends>QWidget</extends>

View File

@ -11,6 +11,7 @@
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_audio.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
ConfigureAudio::ConfigureAudio(QWidget* parent)
@ -24,6 +25,11 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureAudio::UpdateAudioDevices);
ui->volume_label->setVisible(Settings::configuring_global);
ui->volume_combo_box->setVisible(!Settings::configuring_global);
SetupPerGameUI();
SetConfiguration();
const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
@ -41,8 +47,22 @@ void ConfigureAudio::SetConfiguration() {
SetAudioDeviceFromDeviceID();
ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching);
ui->volume_slider->setValue(Settings::values.volume * ui->volume_slider->maximum());
ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum());
if (Settings::configuring_global) {
ui->toggle_audio_stretching->setChecked(
Settings::values.enable_audio_stretching.GetValue());
} else {
ConfigurationShared::SetPerGameSetting(ui->toggle_audio_stretching,
&Settings::values.enable_audio_stretching);
if (Settings::values.volume.UsingGlobal()) {
ui->volume_combo_box->setCurrentIndex(0);
ui->volume_slider->setEnabled(false);
} else {
ui->volume_combo_box->setCurrentIndex(1);
ui->volume_slider->setEnabled(true);
}
}
SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
}
@ -80,15 +100,36 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
}
void ConfigureAudio::ApplyConfiguration() {
Settings::values.sink_id =
ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex())
.toStdString();
Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked();
Settings::values.audio_device_id =
ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex())
.toStdString();
Settings::values.volume =
static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum();
if (Settings::configuring_global) {
Settings::values.sink_id =
ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex())
.toStdString();
Settings::values.audio_device_id =
ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex())
.toStdString();
// Guard if during game and set to game-specific value
if (Settings::values.enable_audio_stretching.UsingGlobal()) {
Settings::values.enable_audio_stretching.SetValue(
ui->toggle_audio_stretching->isChecked());
}
if (Settings::values.volume.UsingGlobal()) {
Settings::values.volume.SetValue(
static_cast<float>(ui->volume_slider->sliderPosition()) /
ui->volume_slider->maximum());
}
} else {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
ui->toggle_audio_stretching);
if (ui->volume_combo_box->currentIndex() == 0) {
Settings::values.volume.SetGlobal(true);
} else {
Settings::values.volume.SetGlobal(false);
Settings::values.volume.SetValue(
static_cast<float>(ui->volume_slider->sliderPosition()) /
ui->volume_slider->maximum());
}
}
}
void ConfigureAudio::changeEvent(QEvent* event) {
@ -122,3 +163,22 @@ void ConfigureAudio::RetranslateUI() {
ui->retranslateUi(this);
SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
}
void ConfigureAudio::SetupPerGameUI() {
if (Settings::configuring_global) {
ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal());
ui->toggle_audio_stretching->setEnabled(
Settings::values.enable_audio_stretching.UsingGlobal());
return;
}
ui->toggle_audio_stretching->setTristate(true);
connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
this, [this](int index) { ui->volume_slider->setEnabled(index == 1); });
ui->output_sink_combo_box->setVisible(false);
ui->output_sink_label->setVisible(false);
ui->audio_device_combo_box->setVisible(false);
ui->audio_device_label->setVisible(false);
}

View File

@ -34,5 +34,7 @@ private:
void SetAudioDeviceFromDeviceID();
void SetVolumeIndicatorText(int percentage);
void SetupPerGameUI();
std::unique_ptr<Ui::ConfigureAudio> ui;
};

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>188</width>
<height>246</height>
<width>367</width>
<height>368</height>
</rect>
</property>
<layout class="QVBoxLayout">
@ -18,9 +18,9 @@
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<layout class="QHBoxLayout" name="_3">
<item>
<widget class="QLabel" name="label_1">
<widget class="QLabel" name="output_sink_label">
<property name="text">
<string>Output Engine:</string>
</property>
@ -31,20 +31,20 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="toggle_audio_stretching">
<property name="toolTip">
<string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string>
</property>
<property name="text">
<string>Enable audio stretching</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<widget class="QCheckBox" name="toggle_audio_stretching">
<property name="toolTip">
<string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string>
</property>
<property name="text">
<string>Enable audio stretching</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="_2">
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="audio_device_label">
<property name="text">
<string>Audio Device:</string>
</property>
@ -61,7 +61,21 @@
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<widget class="QComboBox" name="volume_combo_box">
<item>
<property name="text">
<string>Use global volume</string>
</property>
</item>
<item>
<property name="text">
<string>Set volume:</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="volume_label">
<property name="text">
<string>Volume:</string>
</property>
@ -74,7 +88,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<width>30</width>
<height>20</height>
</size>
</property>

View File

@ -0,0 +1,61 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QComboBox>
#include <QMessageBox>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_cpu.h"
#include "yuzu/configuration/configure_cpu.h"
ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) {
ui->setupUi(this);
SetConfiguration();
connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this,
&ConfigureCpu::AccuracyUpdated);
}
ConfigureCpu::~ConfigureCpu() = default;
void ConfigureCpu::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->accuracy->setEnabled(runtime_lock);
ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy));
}
void ConfigureCpu::AccuracyUpdated(int index) {
if (static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) {
const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"),
tr("CPU Debug Mode is only intended for developer "
"use. Are you sure you want to enable this?"),
QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::No) {
ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate));
return;
}
}
}
void ConfigureCpu::ApplyConfiguration() {
Settings::values.cpu_accuracy =
static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex());
}
void ConfigureCpu::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QWidget::changeEvent(event);
}
void ConfigureCpu::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@ -0,0 +1,33 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QWidget>
#include "core/settings.h"
namespace Ui {
class ConfigureCpu;
}
class ConfigureCpu : public QWidget {
Q_OBJECT
public:
explicit ConfigureCpu(QWidget* parent = nullptr);
~ConfigureCpu() override;
void ApplyConfiguration();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
void AccuracyUpdated(int index);
void SetConfiguration();
std::unique_ptr<Ui::ConfigureCpu> ui;
};

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureCpu</class>
<widget class="QWidget" name="ConfigureCpu">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>321</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox">
<property name="title">
<string>General</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Accuracy:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="accuracy">
<item>
<property name="text">
<string>Accurate</string>
</property>
</item>
<item>
<property name="text">
<string>Enable Debug Mode</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel">
<property name="wordWrap">
<bool>1</bool>
</property>
<property name="text">
<string>We recommend setting accuracy to "Accurate".</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_disable_info">
<property name="text">
<string>CPU settings are available only when game is not running.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,65 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QComboBox>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_cpu_debug.h"
#include "yuzu/configuration/configure_cpu_debug.h"
ConfigureCpuDebug::ConfigureCpuDebug(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureCpuDebug) {
ui->setupUi(this);
SetConfiguration();
}
ConfigureCpuDebug::~ConfigureCpuDebug() = default;
void ConfigureCpuDebug::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->cpuopt_page_tables->setEnabled(runtime_lock);
ui->cpuopt_page_tables->setChecked(Settings::values.cpuopt_page_tables);
ui->cpuopt_block_linking->setEnabled(runtime_lock);
ui->cpuopt_block_linking->setChecked(Settings::values.cpuopt_block_linking);
ui->cpuopt_return_stack_buffer->setEnabled(runtime_lock);
ui->cpuopt_return_stack_buffer->setChecked(Settings::values.cpuopt_return_stack_buffer);
ui->cpuopt_fast_dispatcher->setEnabled(runtime_lock);
ui->cpuopt_fast_dispatcher->setChecked(Settings::values.cpuopt_fast_dispatcher);
ui->cpuopt_context_elimination->setEnabled(runtime_lock);
ui->cpuopt_context_elimination->setChecked(Settings::values.cpuopt_context_elimination);
ui->cpuopt_const_prop->setEnabled(runtime_lock);
ui->cpuopt_const_prop->setChecked(Settings::values.cpuopt_const_prop);
ui->cpuopt_misc_ir->setEnabled(runtime_lock);
ui->cpuopt_misc_ir->setChecked(Settings::values.cpuopt_misc_ir);
ui->cpuopt_reduce_misalign_checks->setEnabled(runtime_lock);
ui->cpuopt_reduce_misalign_checks->setChecked(Settings::values.cpuopt_reduce_misalign_checks);
}
void ConfigureCpuDebug::ApplyConfiguration() {
Settings::values.cpuopt_page_tables = ui->cpuopt_page_tables->isChecked();
Settings::values.cpuopt_block_linking = ui->cpuopt_block_linking->isChecked();
Settings::values.cpuopt_return_stack_buffer = ui->cpuopt_return_stack_buffer->isChecked();
Settings::values.cpuopt_fast_dispatcher = ui->cpuopt_fast_dispatcher->isChecked();
Settings::values.cpuopt_context_elimination = ui->cpuopt_context_elimination->isChecked();
Settings::values.cpuopt_const_prop = ui->cpuopt_const_prop->isChecked();
Settings::values.cpuopt_misc_ir = ui->cpuopt_misc_ir->isChecked();
Settings::values.cpuopt_reduce_misalign_checks = ui->cpuopt_reduce_misalign_checks->isChecked();
}
void ConfigureCpuDebug::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QWidget::changeEvent(event);
}
void ConfigureCpuDebug::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@ -0,0 +1,31 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QWidget>
#include "core/settings.h"
namespace Ui {
class ConfigureCpuDebug;
}
class ConfigureCpuDebug : public QWidget {
Q_OBJECT
public:
explicit ConfigureCpuDebug(QWidget* parent = nullptr);
~ConfigureCpuDebug() override;
void ApplyConfiguration();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
void SetConfiguration();
std::unique_ptr<Ui::ConfigureCpuDebug> ui;
};

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureCpuDebug</class>
<widget class="QWidget" name="ConfigureCpuDebug">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>321</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox">
<property name="title">
<string>Toggle CPU Optimizations</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel">
<property name="wordWrap">
<bool>1</bool>
</property>
<property name="text">
<string>
&lt;div&gt;
&lt;b&gt;For debugging only.&lt;/b&gt;
&lt;br&gt;
If you're not sure what these do, keep all of these enabled.
&lt;br&gt;
These settings only take effect when CPU Accuracy is "Debug Mode".
&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_page_tables">
<property name="text">
<string>Enable inline page tables</string>
</property>
<property name="toolTip">
<string>
&lt;div style="white-space: nowrap"&gt;This optimization speeds up memory accesses by the guest program.&lt;/div&gt;
&lt;div style="white-space: nowrap"&gt;Enabling it inlines accesses to PageTable::pointers into emitted code.&lt;/div&gt;
&lt;div style="white-space: nowrap"&gt;Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_block_linking">
<property name="text">
<string>Enable block linking</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_return_stack_buffer">
<property name="text">
<string>Enable return stack buffer</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;This optimization avoids dispatcher lookups by keeping track potential return addresses of BL instructions. This approximates what happens with a return stack buffer on a real CPU.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_fast_dispatcher">
<property name="text">
<string>Enable fast dispatcher</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;Enable a two-tiered dispatch system. A faster dispatcher written in assembly has a small MRU cache of jump destinations is used first. If that fails, dispatch falls back to the slower C++ dispatcher.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_context_elimination">
<property name="text">
<string>Enable context elimination</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_const_prop">
<property name="text">
<string>Enable constant propagation</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;Enables IR optimizations that involve constant propagation.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_misc_ir">
<property name="text">
<string>Enable miscellaneous optimizations</string>
</property>
<property name="toolTip">
<string>
&lt;div&gt;Enables miscellaneous IR optimizations.&lt;/div&gt;
</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cpuopt_reduce_misalign_checks">
<property name="text">
<string>Enable misalignment check reduction</string>
</property>
<property name="toolTip">
<string>
&lt;div style="white-space: nowrap"&gt;When enabled, a misalignment is only triggered when an access crosses a page boundary.&lt;/div&gt;
&lt;div style="white-space: nowrap"&gt;When disabled, a misalignment is triggered on all misaligned accesses.&lt;/div&gt;
</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_disable_info">
<property name="text">
<string>CPU settings are available only when game is not running.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -36,7 +36,6 @@ void ConfigureDebug::SetConfiguration() {
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
ui->reporting_services->setChecked(Settings::values.reporting_services);
ui->quest_flag->setChecked(Settings::values.quest_flag);
ui->disable_cpu_opt->setChecked(Settings::values.disable_cpu_opt);
ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug);
ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
@ -51,7 +50,6 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
Settings::values.reporting_services = ui->reporting_services->isChecked();
Settings::values.quest_flag = ui->quest_flag->isChecked();
Settings::values.disable_cpu_opt = ui->disable_cpu_opt->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
Debugger::ToggleConsole();

View File

@ -228,13 +228,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="disable_cpu_opt">
<property name="text">
<string>Disable CPU JIT optimizations</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -14,6 +14,8 @@
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
: QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) {
Settings::configuring_global = true;
ui->setupUi(this);
ui->hotkeysTab->Populate(registry);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
@ -40,6 +42,8 @@ void ConfigureDialog::ApplyConfiguration() {
ui->filesystemTab->applyConfiguration();
ui->inputTab->ApplyConfiguration();
ui->hotkeysTab->ApplyConfiguration(registry);
ui->cpuTab->ApplyConfiguration();
ui->cpuDebugTab->ApplyConfiguration();
ui->graphicsTab->ApplyConfiguration();
ui->graphicsAdvancedTab->ApplyConfiguration();
ui->audioTab->ApplyConfiguration();
@ -74,9 +78,10 @@ void ConfigureDialog::RetranslateUI() {
Q_DECLARE_METATYPE(QList<QWidget*>);
void ConfigureDialog::PopulateSelectionList() {
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
const std::array<std::pair<QString, QList<QWidget*>>, 6> items{
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
{tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}},
{tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}},
{tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}},
{tr("Audio"), {ui->audioTab}},
{tr("Controls"), {ui->inputTab, ui->hotkeysTab}}},
@ -105,6 +110,8 @@ void ConfigureDialog::UpdateVisibleTabs() {
{ui->profileManagerTab, tr("Profiles")},
{ui->inputTab, tr("Input")},
{ui->hotkeysTab, tr("Hotkeys")},
{ui->cpuTab, tr("CPU")},
{ui->cpuDebugTab, tr("Debug")},
{ui->graphicsTab, tr("Graphics")},
{ui->graphicsAdvancedTab, tr("Advanced")},
{ui->audioTab, tr("Audio")},

View File

@ -11,19 +11,6 @@
#include "yuzu/configuration/configure_filesystem.h"
#include "yuzu/uisettings.h"
namespace {
template <typename T>
void SetComboBoxFromData(QComboBox* combo_box, T data) {
const auto index = combo_box->findData(QVariant::fromValue(static_cast<u64>(data)));
if (index >= combo_box->count() || index < 0)
return;
combo_box->setCurrentIndex(index);
}
} // Anonymous namespace
ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureFilesystem>()) {
ui->setupUi(this);
@ -73,11 +60,6 @@ void ConfigureFilesystem::setConfiguration() {
ui->cache_game_list->setChecked(UISettings::values.cache_game_list);
SetComboBoxFromData(ui->nand_size, Settings::values.nand_total_size);
SetComboBoxFromData(ui->usrnand_size, Settings::values.nand_user_size);
SetComboBoxFromData(ui->sysnand_size, Settings::values.nand_system_size);
SetComboBoxFromData(ui->sdmc_size, Settings::values.sdmc_size);
UpdateEnabledControls();
}
@ -98,15 +80,6 @@ void ConfigureFilesystem::applyConfiguration() {
Settings::values.dump_nso = ui->dump_nso->isChecked();
UISettings::values.cache_game_list = ui->cache_game_list->isChecked();
Settings::values.nand_total_size = static_cast<Settings::NANDTotalSize>(
ui->nand_size->itemData(ui->nand_size->currentIndex()).toULongLong());
Settings::values.nand_system_size = static_cast<Settings::NANDSystemSize>(
ui->nand_size->itemData(ui->sysnand_size->currentIndex()).toULongLong());
Settings::values.nand_user_size = static_cast<Settings::NANDUserSize>(
ui->nand_size->itemData(ui->usrnand_size->currentIndex()).toULongLong());
Settings::values.sdmc_size = static_cast<Settings::SDMCSize>(
ui->nand_size->itemData(ui->sdmc_size->currentIndex()).toULongLong());
}
void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit) {

View File

@ -115,127 +115,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Storage Sizes</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>SD Card</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>System NAND</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="sysnand_size">
<item>
<property name="text">
<string>2.5 GB</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="sdmc_size">
<property name="currentText">
<string>32 GB</string>
</property>
<item>
<property name="text">
<string>1 GB</string>
</property>
</item>
<item>
<property name="text">
<string>2 GB</string>
</property>
</item>
<item>
<property name="text">
<string>4 GB</string>
</property>
</item>
<item>
<property name="text">
<string>8 GB</string>
</property>
</item>
<item>
<property name="text">
<string>16 GB</string>
</property>
</item>
<item>
<property name="text">
<string>32 GB</string>
</property>
</item>
<item>
<property name="text">
<string>64 GB</string>
</property>
</item>
<item>
<property name="text">
<string>128 GB</string>
</property>
</item>
<item>
<property name="text">
<string>256 GB</string>
</property>
</item>
<item>
<property name="text">
<string>1 TB</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="usrnand_size">
<item>
<property name="text">
<string>26 GB</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>User NAND</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>NAND</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="nand_size">
<item>
<property name="text">
<string>29.1 GB</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">

View File

@ -7,17 +7,21 @@
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_general.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_general.h"
#include "yuzu/uisettings.h"
ConfigureGeneral::ConfigureGeneral(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGeneral) {
ui->setupUi(this);
SetupPerGameUI();
SetConfiguration();
connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled);
connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, [this]() {
ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked);
});
}
ConfigureGeneral::~ConfigureGeneral() = default;
@ -26,27 +30,58 @@ void ConfigureGeneral::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->use_multi_core->setEnabled(runtime_lock);
ui->use_multi_core->setChecked(Settings::values.use_multi_core);
ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue());
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background);
ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked());
ui->frame_limit->setValue(Settings::values.frame_limit);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
if (!Settings::configuring_global) {
if (Settings::values.use_multi_core.UsingGlobal()) {
ui->use_multi_core->setCheckState(Qt::PartiallyChecked);
}
if (Settings::values.use_frame_limit.UsingGlobal()) {
ui->toggle_frame_limit->setCheckState(Qt::PartiallyChecked);
}
}
ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked &&
ui->toggle_frame_limit->isEnabled());
}
void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
if (Settings::configuring_global) {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
Settings::values.frame_limit = ui->frame_limit->value();
Settings::values.use_multi_core = ui->use_multi_core->isChecked();
// Guard if during game and set to game-specific value
if (Settings::values.use_frame_limit.UsingGlobal()) {
Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() ==
Qt::Checked);
Settings::values.frame_limit.SetValue(ui->frame_limit->value());
}
if (Settings::values.use_multi_core.UsingGlobal()) {
Settings::values.use_multi_core.SetValue(ui->use_multi_core->isChecked());
}
} else {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
ui->use_multi_core);
bool global_frame_limit = ui->toggle_frame_limit->checkState() == Qt::PartiallyChecked;
Settings::values.use_frame_limit.SetGlobal(global_frame_limit);
Settings::values.frame_limit.SetGlobal(global_frame_limit);
if (!global_frame_limit) {
Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() ==
Qt::Checked);
Settings::values.frame_limit.SetValue(ui->frame_limit->value());
}
}
}
void ConfigureGeneral::changeEvent(QEvent* event) {
@ -60,3 +95,20 @@ void ConfigureGeneral::changeEvent(QEvent* event) {
void ConfigureGeneral::RetranslateUI() {
ui->retranslateUi(this);
}
void ConfigureGeneral::SetupPerGameUI() {
if (Settings::configuring_global) {
ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal());
ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal());
return;
}
ui->toggle_check_exit->setVisible(false);
ui->toggle_user_on_boot->setVisible(false);
ui->toggle_background_pause->setVisible(false);
ui->toggle_hide_mouse->setVisible(false);
ui->toggle_frame_limit->setTristate(true);
ui->use_multi_core->setTristate(true);
}

View File

@ -28,5 +28,7 @@ private:
void SetConfiguration();
void SetupPerGameUI();
std::unique_ptr<Ui::ConfigureGeneral> ui;
};

View File

@ -13,6 +13,7 @@
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_graphics.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics.h"
#ifdef HAS_VULKAN
@ -21,11 +22,13 @@
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGraphics) {
vulkan_device = Settings::values.vulkan_device;
vulkan_device = Settings::values.vulkan_device.GetValue();
RetrieveVulkanDevices();
ui->setupUi(this);
SetupPerGameUI();
SetConfiguration();
connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this,
@ -40,6 +43,9 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
}
UpdateBackgroundColorButton(new_bg_color);
});
ui->bg_label->setVisible(Settings::configuring_global);
ui->bg_combobox->setVisible(!Settings::configuring_global);
}
void ConfigureGraphics::UpdateDeviceSelection(int device) {
@ -57,27 +63,95 @@ void ConfigureGraphics::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->api->setEnabled(runtime_lock);
ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend));
ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio);
ui->use_disk_shader_cache->setEnabled(runtime_lock);
ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache);
ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation);
UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
Settings::values.bg_blue));
ui->use_disk_shader_cache->setEnabled(runtime_lock);
if (Settings::configuring_global) {
ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
ui->use_asynchronous_gpu_emulation->setChecked(
Settings::values.use_asynchronous_gpu_emulation.GetValue());
} else {
ConfigurationShared::SetPerGameSetting(ui->use_disk_shader_cache,
&Settings::values.use_disk_shader_cache);
ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_gpu_emulation,
&Settings::values.use_asynchronous_gpu_emulation);
ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
&Settings::values.aspect_ratio);
ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
}
UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(),
Settings::values.bg_green.GetValue(),
Settings::values.bg_blue.GetValue()));
UpdateDeviceComboBox();
}
void ConfigureGraphics::ApplyConfiguration() {
Settings::values.renderer_backend = GetCurrentGraphicsBackend();
Settings::values.vulkan_device = vulkan_device;
Settings::values.aspect_ratio = ui->aspect_ratio_combobox->currentIndex();
Settings::values.use_disk_shader_cache = ui->use_disk_shader_cache->isChecked();
Settings::values.use_asynchronous_gpu_emulation =
ui->use_asynchronous_gpu_emulation->isChecked();
Settings::values.bg_red = static_cast<float>(bg_color.redF());
Settings::values.bg_green = static_cast<float>(bg_color.greenF());
Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
if (Settings::configuring_global) {
// Guard if during game and set to game-specific value
if (Settings::values.renderer_backend.UsingGlobal()) {
Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend());
}
if (Settings::values.vulkan_device.UsingGlobal()) {
Settings::values.vulkan_device.SetValue(vulkan_device);
}
if (Settings::values.aspect_ratio.UsingGlobal()) {
Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex());
}
if (Settings::values.use_disk_shader_cache.UsingGlobal()) {
Settings::values.use_disk_shader_cache.SetValue(ui->use_disk_shader_cache->isChecked());
}
if (Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()) {
Settings::values.use_asynchronous_gpu_emulation.SetValue(
ui->use_asynchronous_gpu_emulation->isChecked());
}
if (Settings::values.bg_red.UsingGlobal()) {
Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF()));
Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF()));
Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF()));
}
} else {
if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
Settings::values.renderer_backend.SetGlobal(true);
Settings::values.vulkan_device.SetGlobal(true);
} else {
Settings::values.renderer_backend.SetGlobal(false);
Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend());
if (GetCurrentGraphicsBackend() == Settings::RendererBackend::Vulkan) {
Settings::values.vulkan_device.SetGlobal(false);
Settings::values.vulkan_device.SetValue(vulkan_device);
} else {
Settings::values.vulkan_device.SetGlobal(true);
}
}
ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
ui->aspect_ratio_combobox);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
ui->use_disk_shader_cache);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
ui->use_asynchronous_gpu_emulation);
if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
Settings::values.bg_red.SetGlobal(true);
Settings::values.bg_green.SetGlobal(true);
Settings::values.bg_blue.SetGlobal(true);
} else {
Settings::values.bg_red.SetGlobal(false);
Settings::values.bg_green.SetGlobal(false);
Settings::values.bg_blue.SetGlobal(false);
Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF()));
Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF()));
Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF()));
}
}
}
void ConfigureGraphics::changeEvent(QEvent* event) {
@ -106,6 +180,11 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
ui->device->clear();
bool enabled = false;
if (!Settings::configuring_global &&
ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
vulkan_device = Settings::values.vulkan_device.GetValue();
}
switch (GetCurrentGraphicsBackend()) {
case Settings::RendererBackend::OpenGL:
ui->device->addItem(tr("OpenGL Graphics Device"));
@ -119,6 +198,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
enabled = !vulkan_devices.empty();
break;
}
// If in per-game config and use global is selected, don't enable.
enabled &= !(!Settings::configuring_global &&
ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX);
ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
}
@ -132,5 +214,37 @@ void ConfigureGraphics::RetrieveVulkanDevices() {
}
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
return static_cast<Settings::RendererBackend>(ui->api->currentIndex());
if (Settings::configuring_global) {
return static_cast<Settings::RendererBackend>(ui->api->currentIndex());
}
if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
Settings::values.renderer_backend.SetGlobal(true);
return Settings::values.renderer_backend.GetValue();
}
Settings::values.renderer_backend.SetGlobal(false);
return static_cast<Settings::RendererBackend>(ui->api->currentIndex() -
ConfigurationShared::USE_GLOBAL_OFFSET);
}
void ConfigureGraphics::SetupPerGameUI() {
if (Settings::configuring_global) {
ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal());
ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal());
ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal());
ui->use_asynchronous_gpu_emulation->setEnabled(
Settings::values.use_asynchronous_gpu_emulation.UsingGlobal());
ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal());
ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal());
return;
}
connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this,
[this](int index) { ui->bg_button->setEnabled(index == 1); });
ui->use_disk_shader_cache->setTristate(true);
ui->use_asynchronous_gpu_emulation->setTristate(true);
ConfigurationShared::InsertGlobalItem(ui->aspect_ratio_combobox);
ConfigurationShared::InsertGlobalItem(ui->api);
}

View File

@ -35,6 +35,8 @@ private:
void RetrieveVulkanDevices();
void SetupPerGameUI();
Settings::RendererBackend GetCurrentGraphicsBackend() const;
std::unique_ptr<Ui::ConfigureGraphics> ui;

View File

@ -121,6 +121,29 @@
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QComboBox" name="bg_combobox">
<property name="currentText">
<string>Use global background color</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="maxVisibleItems">
<number>10</number>
</property>
<item>
<property name="text">
<string>Use global background color</string>
</property>
</item>
<item>
<property name="text">
<string>Set background color:</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="bg_label">
<property name="text">
@ -128,6 +151,19 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="bg_button">
<property name="maximumSize">

View File

@ -5,6 +5,7 @@
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_graphics_advanced.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent)
@ -12,6 +13,8 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent)
ui->setupUi(this);
SetupPerGameUI();
SetConfiguration();
}
@ -19,26 +22,81 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
void ConfigureGraphicsAdvanced::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->gpu_accuracy->setCurrentIndex(static_cast<int>(Settings::values.gpu_accuracy));
ui->use_vsync->setEnabled(runtime_lock);
ui->use_vsync->setChecked(Settings::values.use_vsync);
ui->use_assembly_shaders->setEnabled(runtime_lock);
ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders);
ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time);
ui->force_30fps_mode->setEnabled(runtime_lock);
ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode);
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
ui->anisotropic_filtering_combobox->setCurrentIndex(Settings::values.max_anisotropy);
if (Settings::configuring_global) {
ui->gpu_accuracy->setCurrentIndex(
static_cast<int>(Settings::values.gpu_accuracy.GetValue()));
ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
ui->anisotropic_filtering_combobox->setCurrentIndex(
Settings::values.max_anisotropy.GetValue());
} else {
ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy);
ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync);
ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders,
&Settings::values.use_assembly_shaders);
ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time,
&Settings::values.use_fast_gpu_time);
ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode,
&Settings::values.force_30fps_mode);
ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox,
&Settings::values.max_anisotropy);
}
}
void ConfigureGraphicsAdvanced::ApplyConfiguration() {
auto gpu_accuracy = static_cast<Settings::GPUAccuracy>(ui->gpu_accuracy->currentIndex());
Settings::values.gpu_accuracy = gpu_accuracy;
Settings::values.use_vsync = ui->use_vsync->isChecked();
Settings::values.use_assembly_shaders = ui->use_assembly_shaders->isChecked();
Settings::values.use_fast_gpu_time = ui->use_fast_gpu_time->isChecked();
Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked();
Settings::values.max_anisotropy = ui->anisotropic_filtering_combobox->currentIndex();
// Subtract 2 if configuring per-game (separator and "use global configuration" take 2 slots)
const auto gpu_accuracy = static_cast<Settings::GPUAccuracy>(
ui->gpu_accuracy->currentIndex() -
((Settings::configuring_global) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET));
if (Settings::configuring_global) {
// Must guard in case of a during-game configuration when set to be game-specific.
if (Settings::values.gpu_accuracy.UsingGlobal()) {
Settings::values.gpu_accuracy.SetValue(gpu_accuracy);
}
if (Settings::values.use_vsync.UsingGlobal()) {
Settings::values.use_vsync.SetValue(ui->use_vsync->isChecked());
}
if (Settings::values.use_assembly_shaders.UsingGlobal()) {
Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked());
}
if (Settings::values.use_fast_gpu_time.UsingGlobal()) {
Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked());
}
if (Settings::values.force_30fps_mode.UsingGlobal()) {
Settings::values.force_30fps_mode.SetValue(ui->force_30fps_mode->isChecked());
}
if (Settings::values.max_anisotropy.UsingGlobal()) {
Settings::values.max_anisotropy.SetValue(
ui->anisotropic_filtering_combobox->currentIndex());
}
} else {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
ui->anisotropic_filtering_combobox);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
ui->use_assembly_shaders);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
ui->use_fast_gpu_time);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode,
ui->force_30fps_mode);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
ui->anisotropic_filtering_combobox);
if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
Settings::values.gpu_accuracy.SetGlobal(true);
} else {
Settings::values.gpu_accuracy.SetGlobal(false);
Settings::values.gpu_accuracy.SetValue(gpu_accuracy);
}
}
}
void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@ -52,3 +110,25 @@ void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
void ConfigureGraphicsAdvanced::RetranslateUI() {
ui->retranslateUi(this);
}
void ConfigureGraphicsAdvanced::SetupPerGameUI() {
// Disable if not global (only happens during game)
if (Settings::configuring_global) {
ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal());
ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal());
ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal());
ui->anisotropic_filtering_combobox->setEnabled(
Settings::values.max_anisotropy.UsingGlobal());
return;
}
ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy);
ui->use_vsync->setTristate(true);
ui->use_assembly_shaders->setTristate(true);
ui->use_fast_gpu_time->setTristate(true);
ui->force_30fps_mode->setTristate(true);
ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox);
}

Some files were not shown because too many files have changed in this diff Show More