Rebase to master

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

View File

@ -118,8 +118,17 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
# Configure C++ standard # Configure C++ standard
# =========================== # ===========================
set(CMAKE_CXX_STANDARD 17) # boost asio's concept usage doesn't play nicely with some compilers yet.
set(CMAKE_CXX_STANDARD_REQUIRED ON) 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/ # Output binaries to bin/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
@ -151,7 +160,7 @@ macro(yuzu_find_packages)
# Cmake Pkg Prefix Version Conan Pkg # Cmake Pkg Prefix Version Conan Pkg
"Boost 1.71 boost/1.72.0" "Boost 1.71 boost/1.72.0"
"Catch2 2.11 catch2/2.11.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 # can't use until https://github.com/bincrafters/community/issues/1173
#"libzip 1.5 libzip/1.5.2@bincrafters/stable" #"libzip 1.5 libzip/1.5.2@bincrafters/stable"
"lz4 1.8 lz4/1.9.2" "lz4 1.8 lz4/1.9.2"
@ -211,7 +220,7 @@ if(ENABLE_QT)
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
endif() 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) if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
endif() endif()
@ -287,7 +296,7 @@ if (CONAN_REQUIRED_LIBS)
if(ENABLE_QT) if(ENABLE_QT)
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}") list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
list(APPEND CMAKE_PREFIX_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) if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets) find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
endif() endif()
@ -330,13 +339,16 @@ elseif(SDL2_FOUND)
endif() endif()
# Ensure libusb is properly configured (based on dolphin libusb include) # 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) if (NOT LIBUSB_FOUND)
add_subdirectory(externals/libusb) add_subdirectory(externals/libusb)
set(LIBUSB_INCLUDE_DIR "")
set(LIBUSB_LIBRARIES usb) set(LIBUSB_LIBRARIES usb)
endif() endif()
# Prefer the -pthread flag on Linux. # Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)

View File

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

View File

@ -2,7 +2,7 @@ yuzu emulator
============= =============
[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu) [![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/) [![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.gg/XQV6dn9) [![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.com/invite/u77vRWY)
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/). 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/)! 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 ### Development

2
externals/dynarmic vendored

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

View File

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

View File

@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
release_event = Core::Timing::CreateEvent( 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() { void Stream::Play() {
@ -66,15 +66,6 @@ s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const {
return ns.count(); 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) { 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)}; 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()) { if (!IsPlaying()) {
// Ensure we are in playing state before playing the next buffer // Ensure we are in playing state before playing the next buffer
sink_stream.Flush(); sink_stream.Flush();
@ -114,18 +105,17 @@ void Stream::PlayNextBuffer() {
sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
if (core_timing.IsHostTiming()) { core_timing.ScheduleEvent(
core_timing.ScheduleEvent(GetBufferReleaseNSHostTiming(*active_buffer), release_event, {}); GetBufferReleaseNS(*active_buffer) -
} else { (Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late),
core_timing.ScheduleEvent(GetBufferReleaseNS(*active_buffer), release_event, {}); release_event, {});
}
} }
void Stream::ReleaseActiveBuffer() { void Stream::ReleaseActiveBuffer(s64 cycles_late) {
ASSERT(active_buffer); ASSERT(active_buffer);
released_buffers.push(std::move(active_buffer)); released_buffers.push(std::move(active_buffer));
release_callback(); release_callback();
PlayNextBuffer(); PlayNextBuffer(cycles_late);
} }
bool Stream::QueueBuffer(BufferPtr&& buffer) { bool Stream::QueueBuffer(BufferPtr&& buffer) {

View File

@ -90,10 +90,10 @@ public:
private: private:
/// Plays the next queued buffer in the audio stream, starting playback if necessary /// 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 /// 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 /// Gets the number of core cycles when the specified buffer will be released
s64 GetBufferReleaseNS(const Buffer& buffer) const; s64 GetBufferReleaseNS(const Buffer& buffer) const;

View File

@ -11,7 +11,9 @@ namespace Common {
template <typename T> template <typename T>
constexpr T AlignUp(T value, std::size_t size) { constexpr T AlignUp(T value, std::size_t size) {
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 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> template <typename T>

View File

@ -142,10 +142,32 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
// Timing // Timing
config.wall_clock_cntpct = uses_wall_clock; config.wall_clock_cntpct = uses_wall_clock;
// Optimizations // Safe optimizations
if (Settings::values.disable_cpu_opt) { if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
config.enable_optimizations = false; if (!Settings::values.cpuopt_page_tables) {
config.enable_fast_dispatch = false; 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); return std::make_unique<Dynarmic::A32::Jit>(config);

View File

@ -191,15 +191,37 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
// Unpredictable instructions // Unpredictable instructions
config.define_unpredictable_behaviour = true; config.define_unpredictable_behaviour = true;
// Optimizations
if (Settings::values.disable_cpu_opt) {
config.enable_optimizations = false;
config.enable_fast_dispatch = false;
}
// Timing // Timing
config.wall_clock_cntpct = uses_wall_clock; 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); return std::make_shared<Dynarmic::A64::Jit>(config);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
const float window_aspect_ratio = static_cast<float>(height) / width; const float window_aspect_ratio = static_cast<float>(height) / width;
const float emulation_aspect_ratio = EmulationAspectRatio( 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}; const Common::Rectangle<u32> screen_window_area{0, 0, width, height};
Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio); Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio);

View File

@ -123,7 +123,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
: kernel.CreateNewUserProcessID(); : kernel.CreateNewUserProcessID();
process->capabilities.InitializeForMetadatalessProcess(); 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::uniform_int_distribution<u64> distribution;
std::generate(process->random_entropy.begin(), process->random_entropy.end(), std::generate(process->random_entropy.begin(), process->random_entropy.end(),
[&] { return distribution(rng); }); [&] { return distribution(rng); });

View File

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

View File

@ -272,7 +272,7 @@ ISelfController::ISelfController(Core::System& system,
{41, nullptr, "IsSystemBufferSharingEnabled"}, {41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"}, {42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"}, {43, nullptr, "GetSystemSharedBufferHandle"},
{44, nullptr, "CreateManagedDisplaySeparableLayer"}, {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
{45, nullptr, "SetManagedDisplayLayerSeparationMode"}, {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"}, {51, nullptr, "ApproveToDisplay"},
@ -462,6 +462,24 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
rb.Push(*layer_id); 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) { void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_WARNING(Service_AM, "(STUBBED) called");
@ -731,14 +749,14 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
if (Settings::values.use_docked_mode) { if (Settings::values.use_docked_mode) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * 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) * 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 { } else {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * 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) * 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; u32 supported_languages = 0;
FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; 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) { if (res.first != nullptr) {
supported_languages = res.first->GetSupportedLanguages(); supported_languages = res.first->GetSupportedLanguages();
} }

View File

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

View File

@ -121,11 +121,83 @@ public:
{39, nullptr, "PrepareShutdown"}, {39, nullptr, "PrepareShutdown"},
{40, nullptr, "ListApplyDeltaTask"}, {40, nullptr, "ListApplyDeltaTask"},
{41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"}, {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
{42, nullptr, "Unknown1"}, {42, nullptr, "Unknown42"},
{43, nullptr, "Unknown2"}, {43, nullptr, "Unknown43"},
{44, nullptr, "Unknown3"}, {44, nullptr, "Unknown44"},
{45, nullptr, "Unknown4"}, {45, nullptr, "Unknown45"},
{46, nullptr, "Unknown5"}, {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 // clang-format on
@ -142,6 +214,7 @@ public:
{1, nullptr, "RefreshDebugAvailability"}, {1, nullptr, "RefreshDebugAvailability"},
{2, nullptr, "ClearDebugResponse"}, {2, nullptr, "ClearDebugResponse"},
{3, nullptr, "RegisterDebugResponse"}, {3, nullptr, "RegisterDebugResponse"},
{4, nullptr, "IsLargeResourceAvailable"},
}; };
// clang-format on // clang-format on
@ -164,6 +237,8 @@ public:
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "RequestDeviceAuthenticationToken"}, {0, nullptr, "RequestDeviceAuthenticationToken"},
{1, nullptr, "RequestCachedDeviceAuthenticationToken"}, {1, nullptr, "RequestCachedDeviceAuthenticationToken"},
{2, nullptr, "RequestEdgeToken"},
{3, nullptr, "RequestCachedEdgeToken"},
{100, nullptr, "RequestRegisterDeviceAccount"}, {100, nullptr, "RequestRegisterDeviceAccount"},
{101, nullptr, "RequestUnregisterDeviceAccount"}, {101, nullptr, "RequestUnregisterDeviceAccount"},
{102, nullptr, "RequestDeviceAccountStatus"}, {102, nullptr, "RequestDeviceAccountStatus"},
@ -181,7 +256,8 @@ public:
{305, nullptr, "RequestCreateVirtualAccount"}, {305, nullptr, "RequestCreateVirtualAccount"},
{306, nullptr, "RequestDeviceLinkStatus"}, {306, nullptr, "RequestDeviceLinkStatus"},
{400, nullptr, "GetAccountByVirtualAccount"}, {400, nullptr, "GetAccountByVirtualAccount"},
{500, nullptr, "RequestSyncTicket"}, {401, nullptr, "GetVirtualAccount"},
{500, nullptr, "RequestSyncTicketLegacy"},
{501, nullptr, "RequestDownloadTicket"}, {501, nullptr, "RequestDownloadTicket"},
{502, nullptr, "RequestDownloadTicketForPrepurchasedContents"}, {502, nullptr, "RequestDownloadTicketForPrepurchasedContents"},
{503, nullptr, "RequestSyncTicket"}, {503, nullptr, "RequestSyncTicket"},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ namespace Service::SPL {
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)), : 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; Module::Interface::~Interface() = default;

View File

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

View File

@ -90,6 +90,13 @@ public:
: ServiceFramework("ISteadyClock"), clock_core{clock_core}, system{system} { : ServiceFramework("ISteadyClock"), clock_core{clock_core}, system{system} {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, {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); RegisterHandlers(functions);
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -119,13 +119,14 @@ double PerfStats::GetLastFrameTimeScale() {
} }
void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { 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; return;
} }
auto now = Clock::now(); 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 // 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 // speed percent or it will clamp too much and prevent this from properly limiting to that

View File

@ -62,6 +62,7 @@ const std::array<const char*, NumMouseButtons> mapping = {{
} }
Values values = {}; Values values = {};
bool configuring_global = true;
std::string GetTimeZoneString() { std::string GetTimeZoneString() {
static constexpr std::array<const char*, 46> timezones{{ static constexpr std::array<const char*, 46> timezones{{
@ -73,9 +74,9 @@ std::string GetTimeZoneString() {
"UCT", "Universal", "UTC", "W-SU", "WET", "Zulu", "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() { void Apply() {
@ -97,25 +98,25 @@ void LogSetting(const std::string& name, const T& value) {
void LogSettings() { void LogSettings() {
LOG_INFO(Config, "yuzu Configuration:"); LOG_INFO(Config, "yuzu Configuration:");
LogSetting("System_UseDockedMode", Settings::values.use_docked_mode); LogSetting("Controls_UseDockedMode", Settings::values.use_docked_mode);
LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0)); LogSetting("System_RngSeed", Settings::values.rng_seed.GetValue().value_or(0));
LogSetting("System_CurrentUser", Settings::values.current_user); LogSetting("System_CurrentUser", Settings::values.current_user);
LogSetting("System_LanguageIndex", Settings::values.language_index); LogSetting("System_LanguageIndex", Settings::values.language_index.GetValue());
LogSetting("System_RegionIndex", Settings::values.region_index); LogSetting("System_RegionIndex", Settings::values.region_index.GetValue());
LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index); LogSetting("System_TimeZoneIndex", Settings::values.time_zone_index.GetValue());
LogSetting("Core_UseMultiCore", Settings::values.use_multi_core); LogSetting("Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor.GetValue());
LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit); LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue());
LogSetting("Renderer_FrameLimit", Settings::values.frame_limit); LogSetting("Renderer_FrameLimit", Settings::values.frame_limit.GetValue());
LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache); LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache.GetValue());
LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy); LogSetting("Renderer_GPUAccuracyLevel", Settings::values.gpu_accuracy.GetValue());
LogSetting("Renderer_UseAsynchronousGpuEmulation", LogSetting("Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation); Settings::values.use_asynchronous_gpu_emulation.GetValue());
LogSetting("Renderer_UseVsync", Settings::values.use_vsync); LogSetting("Renderer_UseVsync", Settings::values.use_vsync.GetValue());
LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders); LogSetting("Renderer_UseAssemblyShaders", Settings::values.use_assembly_shaders.GetValue());
LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy); LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy.GetValue());
LogSetting("Audio_OutputEngine", Settings::values.sink_id); 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("Audio_OutputDevice", Settings::values.audio_device_id);
LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd); LogSetting("DataStorage_UseVirtualSd", Settings::values.use_virtual_sd);
LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)); LogSetting("DataStorage_NandDir", FileUtil::GetUserPath(FileUtil::UserPath::NANDDir));
@ -131,15 +132,56 @@ float Volume() {
if (values.audio_muted) { if (values.audio_muted) {
return 0.0f; return 0.0f;
} }
return values.volume; return values.volume.GetValue();
} }
bool IsGPULevelExtreme() { bool IsGPULevelExtreme() {
return values.gpu_accuracy == GPUAccuracy::Extreme; return values.gpu_accuracy.GetValue() == GPUAccuracy::Extreme;
} }
bool IsGPULevelHigh() { 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 } // namespace Settings

View File

@ -346,31 +346,6 @@ struct TouchscreenInput {
u32 rotation_angle; 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 { enum class RendererBackend {
OpenGL = 0, OpenGL = 0,
Vulkan = 1, Vulkan = 1,
@ -382,20 +357,102 @@ enum class GPUAccuracy : u32 {
Extreme = 2, 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 { 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 // System
bool use_docked_mode; Setting<std::optional<u32>> rng_seed;
std::optional<u32> rng_seed;
// Measured in seconds since epoch // 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` // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
std::chrono::seconds custom_rtc_differential; std::chrono::seconds custom_rtc_differential;
s32 current_user; s32 current_user;
s32 language_index; Setting<s32> language_index;
s32 region_index; Setting<s32> region_index;
s32 time_zone_index; Setting<s32> time_zone_index;
s32 sound_index; Setting<s32> sound_index;
// Controls // Controls
std::array<PlayerInput, 10> players; std::array<PlayerInput, 10> players;
@ -419,51 +476,13 @@ struct Values {
u16 udp_input_port; u16 udp_input_port;
u8 udp_pad_index; u8 udp_pad_index;
// Core bool use_docked_mode;
bool use_multi_core;
// Data Storage // Data Storage
bool use_virtual_sd; bool use_virtual_sd;
bool gamecard_inserted; bool gamecard_inserted;
bool gamecard_current_game; bool gamecard_current_game;
std::string gamecard_path; 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 // Debugging
bool record_frame_times; bool record_frame_times;
@ -474,10 +493,13 @@ struct Values {
bool dump_nso; bool dump_nso;
bool reporting_services; bool reporting_services;
bool quest_flag; bool quest_flag;
bool disable_cpu_opt;
bool disable_macro_jit; bool disable_macro_jit;
// BCAT // Misceallaneous
std::string log_filter;
bool use_dev_keys;
// Services
std::string bcat_backend; std::string bcat_backend;
bool bcat_boxcat_local; bool bcat_boxcat_local;
@ -501,4 +523,7 @@ std::string GetTimeZoneString();
void Apply(); void Apply();
void LogSettings(); void LogSettings();
// Restore the global state of all applicable settings in the Values struct
void RestoreGlobalState();
} // namespace Settings } // namespace Settings

View File

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

View File

@ -30,7 +30,8 @@ if(SDL2_FOUND)
target_compile_definitions(input_common PRIVATE HAVE_SDL2) target_compile_definitions(input_common PRIVATE HAVE_SDL2)
endif() 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) create_target_directory_groups(input_common)
target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost) target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost)

View File

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <libusb.h>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "input_common/gcadapter/gc_adapter.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 = {}; GCPadStatus pad = {};
ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4); ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
@ -205,7 +206,7 @@ void Adapter::StartScanThread() {
} }
detect_thread_running = true; detect_thread_running = true;
detect_thread = std::thread([=] { ScanThreadFunc(); }); detect_thread = std::thread(&Adapter::ScanThreadFunc, this);
} }
void Adapter::StopScanThread() { void Adapter::StopScanThread() {
@ -234,7 +235,7 @@ void Adapter::Setup() {
} }
if (devices != nullptr) { 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])) { if (CheckDeviceAccess(devices[index])) {
// GC Adapter found and accessible, registering it // GC Adapter found and accessible, registering it
GetGCEndpoint(devices[index]); 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; 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; adapter_controllers_status[port] = ControllerTypes::None;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,7 +96,8 @@ public:
} }
if (is_written) { if (is_written) {
map->MarkAsModified(true, GetModifiedTicks()); 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); MarkForAsyncFlush(map);
} }
if (!map->is_written) { if (!map->is_written) {
@ -369,7 +370,8 @@ private:
} }
if (modified_inheritance) { if (modified_inheritance) {
map->MarkAsModified(true, GetModifiedTicks()); 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); MarkForAsyncFlush(map);
} }
} }

View File

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

View File

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

View File

@ -18,7 +18,7 @@ RendererBase::~RendererBase() = default;
void RendererBase::RefreshBaseSettings() { void RendererBase::RefreshBaseSettings() {
UpdateCurrentFramebufferLayout(); 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; renderer_settings.set_background_color = true;
} }

View File

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

View File

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

View File

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

View File

@ -409,7 +409,7 @@ bool RendererVulkan::PickDevices() {
return false; 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())) { if (device_index < 0 || device_index >= static_cast<s32>(devices->size())) {
LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
return false; return false;

View File

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

View File

@ -121,7 +121,7 @@ void VKStreamBuffer::CreateBuffers(VkBufferUsageFlags usage) {
// Substract from the preferred heap size some bytes to avoid getting out of memory. // 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 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; VkBufferCreateInfo buffer_ci;
buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;

View File

@ -249,7 +249,7 @@ public:
auto& surface = render_targets[index].target; auto& surface = render_targets[index].target;
surface->MarkAsRenderTarget(false, NO_RT); surface->MarkAsRenderTarget(false, NO_RT);
const auto& cr_params = surface->GetSurfaceParams(); 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); AsyncFlushSurface(surface);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -13,17 +13,20 @@
#include "input_common/udp/client.h" #include "input_common/udp/client.h"
#include "yuzu/configuration/config.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. // 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); FileUtil::CreateFullPath(qt_config_loc);
qt_config = qt_config =
std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
global = is_global;
Reload(); Reload();
} }
Config::~Config() { Config::~Config() {
Save(); if (global) {
Save();
}
} }
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
@ -402,16 +405,19 @@ void Config::ApplyDefaultProfileIfInputInvalid() {
void Config::ReadAudioValues() { void Config::ReadAudioValues() {
qt_config->beginGroup(QStringLiteral("Audio")); qt_config->beginGroup(QStringLiteral("Audio"));
Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) if (global) {
.toString() Settings::values.sink_id =
.toStdString(); ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto"))
Settings::values.enable_audio_stretching = .toString()
ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool(); .toStdString();
Settings::values.audio_device_id = Settings::values.audio_device_id =
ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto"))
.toString() .toString()
.toStdString(); .toStdString();
Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat(); }
ReadSettingGlobal(Settings::values.enable_audio_stretching,
QStringLiteral("enable_audio_stretching"), true);
ReadSettingGlobal(Settings::values.volume, QStringLiteral("volume"), 1);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -440,6 +446,8 @@ void Config::ReadControlValues() {
.toInt()); .toInt());
Settings::values.udp_pad_index = Settings::values.udp_pad_index =
static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); 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(); qt_config->endGroup();
} }
@ -447,7 +455,7 @@ void Config::ReadControlValues() {
void Config::ReadCoreValues() { void Config::ReadCoreValues() {
qt_config->beginGroup(QStringLiteral("Core")); 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(); qt_config->endGroup();
} }
@ -497,22 +505,6 @@ void Config::ReadDataStorageValues() {
ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool();
Settings::values.gamecard_path = Settings::values.gamecard_path =
ReadSetting(QStringLiteral("gamecard_path"), QStringLiteral("")).toString().toStdString(); 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(); qt_config->endGroup();
} }
@ -532,8 +524,6 @@ void Config::ReadDebuggingValues() {
Settings::values.reporting_services = Settings::values.reporting_services =
ReadSetting(QStringLiteral("reporting_services"), false).toBool(); ReadSetting(QStringLiteral("reporting_services"), false).toBool();
Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), 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 = Settings::values.disable_macro_jit =
ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool();
@ -625,35 +615,59 @@ void Config::ReadPathValues() {
qt_config->endGroup(); 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() { void Config::ReadRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer")); qt_config->beginGroup(QStringLiteral("Renderer"));
Settings::values.renderer_backend = ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0);
static_cast<Settings::RendererBackend>(ReadSetting(QStringLiteral("backend"), 0).toInt()); ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false);
Settings::values.renderer_debug = ReadSetting(QStringLiteral("debug"), false).toBool(); ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0);
Settings::values.vulkan_device = ReadSetting(QStringLiteral("vulkan_device"), 0).toInt(); ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0);
Settings::values.aspect_ratio = ReadSetting(QStringLiteral("aspect_ratio"), 0).toInt(); ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0);
Settings::values.max_anisotropy = ReadSetting(QStringLiteral("max_anisotropy"), 0).toInt(); ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true);
Settings::values.use_frame_limit = ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100);
ReadSetting(QStringLiteral("use_frame_limit"), true).toBool(); ReadSettingGlobal(Settings::values.use_disk_shader_cache,
Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toUInt(); QStringLiteral("use_disk_shader_cache"), true);
Settings::values.use_disk_shader_cache = ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 0);
ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool(); ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation,
const int gpu_accuracy_level = ReadSetting(QStringLiteral("gpu_accuracy"), 0).toInt(); QStringLiteral("use_asynchronous_gpu_emulation"), false);
Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(gpu_accuracy_level); ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true);
Settings::values.use_asynchronous_gpu_emulation = ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"),
ReadSetting(QStringLiteral("use_asynchronous_gpu_emulation"), false).toBool(); false);
Settings::values.use_vsync = ReadSetting(QStringLiteral("use_vsync"), true).toBool(); ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"),
Settings::values.use_assembly_shaders = true);
ReadSetting(QStringLiteral("use_assembly_shaders"), false).toBool(); ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false);
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();
Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat(); ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0);
Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat(); ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0);
Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat(); ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -682,35 +696,45 @@ void Config::ReadShortcutValues() {
void Config::ReadSystemValues() { void Config::ReadSystemValues() {
qt_config->beginGroup(QStringLiteral("System")); qt_config->beginGroup(QStringLiteral("System"));
Settings::values.use_docked_mode = ReadSettingGlobal(Settings::values.current_user, QStringLiteral("current_user"), 0);
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); Settings::values.current_user =
std::clamp<int>(Settings::values.current_user, 0, Service::Account::MAX_USERS - 1);
Settings::values.current_user = std::clamp<int>( ReadSettingGlobal(Settings::values.language_index, QStringLiteral("language_index"), 1);
ReadSetting(QStringLiteral("current_user"), 0).toInt(), 0, Service::Account::MAX_USERS - 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(); bool rng_seed_enabled;
ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false);
const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool(); bool rng_seed_global =
if (rng_seed_enabled) { global || qt_config->value(QStringLiteral("rng_seed/use_global"), true).toBool();
Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong(); Settings::values.rng_seed.SetGlobal(rng_seed_global);
} else { if (global || !rng_seed_global) {
Settings::values.rng_seed = std::nullopt; 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 = bool custom_rtc_enabled;
ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false);
if (custom_rtc_enabled) { bool custom_rtc_global =
Settings::values.custom_rtc = global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool();
std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()); Settings::values.custom_rtc.SetGlobal(custom_rtc_global);
} else { if (global || !custom_rtc_global) {
Settings::values.custom_rtc = std::nullopt; 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(); qt_config->endGroup();
} }
@ -804,18 +828,21 @@ void Config::ReadWebServiceValues() {
} }
void Config::ReadValues() { void Config::ReadValues() {
ReadControlValues(); if (global) {
ReadControlValues();
ReadDataStorageValues();
ReadDebuggingValues();
ReadDisabledAddOnValues();
ReadServiceValues();
ReadUIValues();
ReadWebServiceValues();
ReadMiscellaneousValues();
}
ReadCoreValues(); ReadCoreValues();
ReadCpuValues();
ReadRendererValues(); ReadRendererValues();
ReadAudioValues(); ReadAudioValues();
ReadDataStorageValues();
ReadSystemValues(); ReadSystemValues();
ReadMiscellaneousValues();
ReadDebuggingValues();
ReadWebServiceValues();
ReadServiceValues();
ReadDisabledAddOnValues();
ReadUIValues();
} }
void Config::SavePlayerValues() { void Config::SavePlayerValues() {
@ -902,30 +929,36 @@ void Config::SaveTouchscreenValues() {
} }
void Config::SaveValues() { void Config::SaveValues() {
SaveControlValues(); if (global) {
SaveControlValues();
SaveDataStorageValues();
SaveDebuggingValues();
SaveDisabledAddOnValues();
SaveServiceValues();
SaveUIValues();
SaveWebServiceValues();
SaveMiscellaneousValues();
}
SaveCoreValues(); SaveCoreValues();
SaveCpuValues();
SaveRendererValues(); SaveRendererValues();
SaveAudioValues(); SaveAudioValues();
SaveDataStorageValues();
SaveSystemValues(); SaveSystemValues();
SaveMiscellaneousValues();
SaveDebuggingValues();
SaveWebServiceValues();
SaveServiceValues();
SaveDisabledAddOnValues();
SaveUIValues();
} }
void Config::SaveAudioValues() { void Config::SaveAudioValues() {
qt_config->beginGroup(QStringLiteral("Audio")); qt_config->beginGroup(QStringLiteral("Audio"));
WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id), if (global) {
QStringLiteral("auto")); WriteSetting(QStringLiteral("output_engine"),
WriteSetting(QStringLiteral("enable_audio_stretching"), QString::fromStdString(Settings::values.sink_id), QStringLiteral("auto"));
Settings::values.enable_audio_stretching, true); WriteSetting(QStringLiteral("output_device"),
WriteSetting(QStringLiteral("output_device"), QString::fromStdString(Settings::values.audio_device_id),
QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto")); QStringLiteral("auto"));
WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f); }
WriteSettingGlobal(QStringLiteral("enable_audio_stretching"),
Settings::values.enable_audio_stretching, true);
WriteSettingGlobal(QStringLiteral("volume"), Settings::values.volume, 1.0f);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -948,6 +981,7 @@ void Config::SaveControlValues() {
WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port,
InputCommon::CemuhookUDP::DEFAULT_PORT); InputCommon::CemuhookUDP::DEFAULT_PORT);
WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); 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(); qt_config->endGroup();
} }
@ -955,7 +989,7 @@ void Config::SaveControlValues() {
void Config::SaveCoreValues() { void Config::SaveCoreValues() {
qt_config->beginGroup(QStringLiteral("Core")); 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(); qt_config->endGroup();
} }
@ -984,18 +1018,7 @@ void Config::SaveDataStorageValues() {
false); false);
WriteSetting(QStringLiteral("gamecard_path"), WriteSetting(QStringLiteral("gamecard_path"),
QString::fromStdString(Settings::values.gamecard_path), QStringLiteral("")); 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(); qt_config->endGroup();
} }
@ -1011,7 +1034,6 @@ void Config::SaveDebuggingValues() {
WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, 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); WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false);
qt_config->endGroup(); qt_config->endGroup();
@ -1075,32 +1097,63 @@ void Config::SavePathValues() {
qt_config->endGroup(); 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() { void Config::SaveRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer")); 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("debug"), Settings::values.renderer_debug, false);
WriteSetting(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0);
WriteSetting(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0);
WriteSetting(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0);
WriteSetting(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true);
WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); WriteSettingGlobal(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100);
WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache, WriteSettingGlobal(QStringLiteral("use_disk_shader_cache"),
true); Settings::values.use_disk_shader_cache, true);
WriteSetting(QStringLiteral("gpu_accuracy"), static_cast<int>(Settings::values.gpu_accuracy), WriteSettingGlobal(QStringLiteral("gpu_accuracy"),
0); static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)),
WriteSetting(QStringLiteral("use_asynchronous_gpu_emulation"), Settings::values.gpu_accuracy.UsingGlobal(), 0);
Settings::values.use_asynchronous_gpu_emulation, false); WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"),
WriteSetting(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); Settings::values.use_asynchronous_gpu_emulation, false);
WriteSetting(QStringLiteral("use_assembly_shaders"), Settings::values.use_assembly_shaders, WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
false); WriteSettingGlobal(QStringLiteral("use_assembly_shaders"),
WriteSetting(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, true); Settings::values.use_assembly_shaders, false);
WriteSetting(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, 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 // 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); WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0);
WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0); WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0);
WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0); WriteSettingGlobal(QStringLiteral("bg_blue"), Settings::values.bg_blue, 0.0);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -1128,23 +1181,28 @@ void Config::SaveShortcutValues() {
void Config::SaveSystemValues() { void Config::SaveSystemValues() {
qt_config->beginGroup(QStringLiteral("System")); 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("current_user"), Settings::values.current_user, 0);
WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1); WriteSettingGlobal(QStringLiteral("language_index"), Settings::values.language_index, 1);
WriteSetting(QStringLiteral("region_index"), Settings::values.region_index, 1); WriteSettingGlobal(QStringLiteral("region_index"), Settings::values.region_index, 1);
WriteSetting(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0); WriteSettingGlobal(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0);
WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false); WriteSettingGlobal(QStringLiteral("rng_seed_enabled"),
WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0); 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(), WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"),
false); Settings::values.custom_rtc.GetValue(global).has_value(),
WriteSetting(QStringLiteral("custom_rtc"), Settings::values.custom_rtc.UsingGlobal(), false);
QVariant::fromValue<long long>( WriteSettingGlobal(
Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), QStringLiteral("custom_rtc"),
0); 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(); qt_config->endGroup();
} }
@ -1236,6 +1294,34 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value)
return result; 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) { void Config::WriteSetting(const QString& name, const QVariant& value) {
qt_config->setValue(name, value); qt_config->setValue(name, value);
} }
@ -1246,6 +1332,40 @@ void Config::WriteSetting(const QString& name, const QVariant& value,
qt_config->setValue(name, 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() { void Config::Reload() {
ReadValues(); ReadValues();
// To apply default value changes // To apply default value changes

View File

@ -7,6 +7,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <string> #include <string>
#include <QMetaType>
#include <QVariant> #include <QVariant>
#include "core/settings.h" #include "core/settings.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
@ -15,7 +16,7 @@ class QSettings;
class Config { class Config {
public: public:
Config(); explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true);
~Config(); ~Config();
void Reload(); void Reload();
@ -48,6 +49,7 @@ private:
void ReadDisabledAddOnValues(); void ReadDisabledAddOnValues();
void ReadMiscellaneousValues(); void ReadMiscellaneousValues();
void ReadPathValues(); void ReadPathValues();
void ReadCpuValues();
void ReadRendererValues(); void ReadRendererValues();
void ReadShortcutValues(); void ReadShortcutValues();
void ReadSystemValues(); void ReadSystemValues();
@ -72,6 +74,7 @@ private:
void SaveDisabledAddOnValues(); void SaveDisabledAddOnValues();
void SaveMiscellaneousValues(); void SaveMiscellaneousValues();
void SavePathValues(); void SavePathValues();
void SaveCpuValues();
void SaveRendererValues(); void SaveRendererValues();
void SaveShortcutValues(); void SaveShortcutValues();
void SaveSystemValues(); void SaveSystemValues();
@ -82,9 +85,33 @@ private:
QVariant ReadSetting(const QString& name) const; QVariant ReadSetting(const QString& name) const;
QVariant ReadSetting(const QString& name, const QVariant& default_value) 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);
void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_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::unique_ptr<QSettings> qt_config;
std::string qt_config_loc; std::string qt_config_loc;
bool global;
}; };
// These metatype declarations cannot be in core/settings.h because core is devoid of QT
Q_DECLARE_METATYPE(Settings::RendererBackend);
Q_DECLARE_METATYPE(Settings::GPUAccuracy);

View File

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

View File

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

View File

@ -78,6 +78,16 @@
<string>Hotkeys</string> <string>Hotkeys</string>
</attribute> </attribute>
</widget> </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"> <widget class="ConfigureGraphics" name="graphicsTab">
<attribute name="title"> <attribute name="title">
<string>Graphics</string> <string>Graphics</string>
@ -158,6 +168,18 @@
<header>configuration/configure_debug.h</header> <header>configuration/configure_debug.h</header>
<container>1</container> <container>1</container>
</customwidget> </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> <customwidget>
<class>ConfigureGraphics</class> <class>ConfigureGraphics</class>
<extends>QWidget</extends> <extends>QWidget</extends>

View File

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

View File

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

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>188</width> <width>367</width>
<height>246</height> <height>368</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
@ -18,9 +18,9 @@
</property> </property>
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
<item> <item>
<layout class="QHBoxLayout"> <layout class="QHBoxLayout" name="_3">
<item> <item>
<widget class="QLabel" name="label_1"> <widget class="QLabel" name="output_sink_label">
<property name="text"> <property name="text">
<string>Output Engine:</string> <string>Output Engine:</string>
</property> </property>
@ -31,20 +31,20 @@
</item> </item>
</layout> </layout>
</item> </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> <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> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="audio_device_label">
<property name="text"> <property name="text">
<string>Audio Device:</string> <string>Audio Device:</string>
</property> </property>
@ -61,7 +61,21 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <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"> <property name="text">
<string>Volume:</string> <string>Volume:</string>
</property> </property>
@ -74,7 +88,7 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>30</width>
<height>20</height> <height>20</height>
</size> </size>
</property> </property>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,19 +11,6 @@
#include "yuzu/configuration/configure_filesystem.h" #include "yuzu/configuration/configure_filesystem.h"
#include "yuzu/uisettings.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) ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureFilesystem>()) { : QWidget(parent), ui(std::make_unique<Ui::ConfigureFilesystem>()) {
ui->setupUi(this); ui->setupUi(this);
@ -73,11 +60,6 @@ void ConfigureFilesystem::setConfiguration() {
ui->cache_game_list->setChecked(UISettings::values.cache_game_list); 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(); UpdateEnabledControls();
} }
@ -98,15 +80,6 @@ void ConfigureFilesystem::applyConfiguration() {
Settings::values.dump_nso = ui->dump_nso->isChecked(); Settings::values.dump_nso = ui->dump_nso->isChecked();
UISettings::values.cache_game_list = ui->cache_game_list->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) { void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit) {

View File

@ -115,127 +115,6 @@
</layout> </layout>
</widget> </widget>
</item> </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> <item>
<widget class="QGroupBox" name="groupBox_4"> <widget class="QGroupBox" name="groupBox_4">
<property name="title"> <property name="title">

View File

@ -7,17 +7,21 @@
#include "core/core.h" #include "core/core.h"
#include "core/settings.h" #include "core/settings.h"
#include "ui_configure_general.h" #include "ui_configure_general.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_general.h" #include "yuzu/configuration/configure_general.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
ConfigureGeneral::ConfigureGeneral(QWidget* parent) ConfigureGeneral::ConfigureGeneral(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGeneral) { : QWidget(parent), ui(new Ui::ConfigureGeneral) {
ui->setupUi(this); ui->setupUi(this);
SetupPerGameUI();
SetConfiguration(); 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; ConfigureGeneral::~ConfigureGeneral() = default;
@ -26,27 +30,58 @@ void ConfigureGeneral::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
ui->use_multi_core->setEnabled(runtime_lock); 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_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); 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_background_pause->setChecked(UISettings::values.pause_when_in_background);
ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
ui->frame_limit->setValue(Settings::values.frame_limit);
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() { void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); if (Settings::configuring_global) {
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->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(); // Guard if during game and set to game-specific value
Settings::values.frame_limit = ui->frame_limit->value(); if (Settings::values.use_frame_limit.UsingGlobal()) {
Settings::values.use_multi_core = ui->use_multi_core->isChecked(); 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) { void ConfigureGeneral::changeEvent(QEvent* event) {
@ -60,3 +95,20 @@ void ConfigureGeneral::changeEvent(QEvent* event) {
void ConfigureGeneral::RetranslateUI() { void ConfigureGeneral::RetranslateUI() {
ui->retranslateUi(this); ui->retranslateUi(this);
} }
void ConfigureGeneral::SetupPerGameUI() {
if (Settings::configuring_global) {
ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal());
ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal());
return;
}
ui->toggle_check_exit->setVisible(false);
ui->toggle_user_on_boot->setVisible(false);
ui->toggle_background_pause->setVisible(false);
ui->toggle_hide_mouse->setVisible(false);
ui->toggle_frame_limit->setTristate(true);
ui->use_multi_core->setTristate(true);
}

View File

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

View File

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

View File

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

View File

@ -121,6 +121,29 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <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> <item>
<widget class="QLabel" name="bg_label"> <widget class="QLabel" name="bg_label">
<property name="text"> <property name="text">
@ -128,6 +151,19 @@
</property> </property>
</widget> </widget>
</item> </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> <item>
<widget class="QPushButton" name="bg_button"> <widget class="QPushButton" name="bg_button">
<property name="maximumSize"> <property name="maximumSize">

View File

@ -5,6 +5,7 @@
#include "core/core.h" #include "core/core.h"
#include "core/settings.h" #include "core/settings.h"
#include "ui_configure_graphics_advanced.h" #include "ui_configure_graphics_advanced.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics_advanced.h" #include "yuzu/configuration/configure_graphics_advanced.h"
ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent) ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent)
@ -12,6 +13,8 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
SetupPerGameUI();
SetConfiguration(); SetConfiguration();
} }
@ -19,26 +22,81 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
void ConfigureGraphicsAdvanced::SetConfiguration() { void ConfigureGraphicsAdvanced::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); 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->setEnabled(runtime_lock);
ui->use_vsync->setChecked(Settings::values.use_vsync);
ui->use_assembly_shaders->setEnabled(runtime_lock); 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->setEnabled(runtime_lock);
ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode);
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 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() { void ConfigureGraphicsAdvanced::ApplyConfiguration() {
auto gpu_accuracy = static_cast<Settings::GPUAccuracy>(ui->gpu_accuracy->currentIndex()); // Subtract 2 if configuring per-game (separator and "use global configuration" take 2 slots)
Settings::values.gpu_accuracy = gpu_accuracy; const auto gpu_accuracy = static_cast<Settings::GPUAccuracy>(
Settings::values.use_vsync = ui->use_vsync->isChecked(); ui->gpu_accuracy->currentIndex() -
Settings::values.use_assembly_shaders = ui->use_assembly_shaders->isChecked(); ((Settings::configuring_global) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET));
Settings::values.use_fast_gpu_time = ui->use_fast_gpu_time->isChecked();
Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked(); if (Settings::configuring_global) {
Settings::values.max_anisotropy = ui->anisotropic_filtering_combobox->currentIndex(); // 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) { void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@ -52,3 +110,25 @@ void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
void ConfigureGraphicsAdvanced::RetranslateUI() { void ConfigureGraphicsAdvanced::RetranslateUI() {
ui->retranslateUi(this); 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