mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Rebase to master
This commit is contained in:
		
						commit
						93fe982a0c
					
				@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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>.*
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ yuzu emulator
 | 
			
		||||
=============
 | 
			
		||||
[](https://travis-ci.com/yuzu-emu/yuzu)
 | 
			
		||||
[](https://dev.azure.com/yuzu-emu/yuzu/)
 | 
			
		||||
[](https://discord.gg/XQV6dn9)
 | 
			
		||||
[](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
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								externals/dynarmic
									
									
									
									
										vendored
									
									
								
							@ -1 +1 @@
 | 
			
		||||
Subproject commit 4f967387c07365b7ea35d2fa3e19b7df8872a09b
 | 
			
		||||
Subproject commit 82417da7803e2cf18efc28a1cd3f3d0a4b6045ae
 | 
			
		||||
@ -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)};
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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); });
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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"},
 | 
			
		||||
 | 
			
		||||
@ -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"},
 | 
			
		||||
 | 
			
		||||
@ -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"},
 | 
			
		||||
 | 
			
		||||
@ -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> {
 | 
			
		||||
 | 
			
		||||
@ -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"},
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,8 @@ public:
 | 
			
		||||
            {4, nullptr, "Cancel"},
 | 
			
		||||
            {5, nullptr, "PrintModuleInformation"},
 | 
			
		||||
            {6, nullptr, "GetModuleInformation"},
 | 
			
		||||
            {10, nullptr, "Unknown10"},
 | 
			
		||||
            {11, nullptr, "Unknown11"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ public:
 | 
			
		||||
            {15, nullptr, "GetBatteryAgePercentage"},
 | 
			
		||||
            {16, nullptr, "GetBatteryChargeInfoEvent"},
 | 
			
		||||
            {17, nullptr, "GetBatteryChargeInfoFields"},
 | 
			
		||||
            {18, nullptr, "GetBatteryChargeCalibratedEvent"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ public:
 | 
			
		||||
    ~SFDNSRES() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void GetAddrInfo(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetAddrInfoRequest(Kernel::HLERequestContext& ctx);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::Sockets
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
 | 
			
		||||
@ -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};
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								src/yuzu/configuration/configuration_shared.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/yuzu/configuration/configuration_shared.cpp
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								src/yuzu/configuration/configuration_shared.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/yuzu/configuration/configuration_shared.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,5 +34,7 @@ private:
 | 
			
		||||
    void SetAudioDeviceFromDeviceID();
 | 
			
		||||
    void SetVolumeIndicatorText(int percentage);
 | 
			
		||||
 | 
			
		||||
    void SetupPerGameUI();
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Ui::ConfigureAudio> ui;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								src/yuzu/configuration/configure_cpu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/yuzu/configuration/configure_cpu.cpp
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/yuzu/configuration/configure_cpu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/yuzu/configuration/configure_cpu.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										92
									
								
								src/yuzu/configuration/configure_cpu.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/yuzu/configuration/configure_cpu.ui
									
									
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										65
									
								
								src/yuzu/configuration/configure_cpu_debug.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/yuzu/configuration/configure_cpu_debug.cpp
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/yuzu/configuration/configure_cpu_debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/yuzu/configuration/configure_cpu_debug.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										174
									
								
								src/yuzu/configuration/configure_cpu_debug.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/yuzu/configuration/configure_cpu_debug.ui
									
									
									
									
									
										Normal 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>
 | 
			
		||||
            <div>
 | 
			
		||||
            <b>For debugging only.</b>
 | 
			
		||||
            <br>
 | 
			
		||||
            If you're not sure what these do, keep all of these enabled.
 | 
			
		||||
            <br>
 | 
			
		||||
            These settings only take effect when CPU Accuracy is "Debug Mode".
 | 
			
		||||
            </div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div>
 | 
			
		||||
            <div style="white-space: nowrap">Enabling it inlines accesses to PageTable::pointers into emitted code.</div>
 | 
			
		||||
            <div style="white-space: nowrap">Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>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.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>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.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>Enables IR optimizations that involve constant propagation.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div>Enables miscellaneous IR optimizations.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
            <div style="white-space: nowrap">When enabled, a misalignment is only triggered when an access crosses a page boundary.</div>
 | 
			
		||||
            <div style="white-space: nowrap">When disabled, a misalignment is triggered on all misaligned accesses.</div>
 | 
			
		||||
           </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>
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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")},
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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">
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,5 +28,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    void SetConfiguration();
 | 
			
		||||
 | 
			
		||||
    void SetupPerGameUI();
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Ui::ConfigureGeneral> ui;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,8 @@ private:
 | 
			
		||||
 | 
			
		||||
    void RetrieveVulkanDevices();
 | 
			
		||||
 | 
			
		||||
    void SetupPerGameUI();
 | 
			
		||||
 | 
			
		||||
    Settings::RendererBackend GetCurrentGraphicsBackend() const;
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Ui::ConfigureGraphics> ui;
 | 
			
		||||
 | 
			
		||||
@ -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">
 | 
			
		||||
 | 
			
		||||
@ -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
		Loading…
	
		Reference in New Issue
	
	Block a user