diff options
Diffstat (limited to 'src')
166 files changed, 5753 insertions, 3104 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 207c7a0a6..d20e6c3b5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -102,6 +102,7 @@ add_library(common STATIC | |||
| 102 | atomic_ops.h | 102 | atomic_ops.h |
| 103 | detached_tasks.cpp | 103 | detached_tasks.cpp |
| 104 | detached_tasks.h | 104 | detached_tasks.h |
| 105 | bit_cast.h | ||
| 105 | bit_field.h | 106 | bit_field.h |
| 106 | bit_util.h | 107 | bit_util.h |
| 107 | cityhash.cpp | 108 | cityhash.cpp |
diff --git a/src/common/bit_cast.h b/src/common/bit_cast.h new file mode 100644 index 000000000..a32a063d1 --- /dev/null +++ b/src/common/bit_cast.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <cstring> | ||
| 8 | #include <type_traits> | ||
| 9 | |||
| 10 | namespace Common { | ||
| 11 | |||
| 12 | template <typename To, typename From> | ||
| 13 | [[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && | ||
| 14 | std::is_trivially_copyable_v<To>, | ||
| 15 | To> | ||
| 16 | BitCast(const From& src) noexcept { | ||
| 17 | To dst; | ||
| 18 | std::memcpy(&dst, &src, sizeof(To)); | ||
| 19 | return dst; | ||
| 20 | } | ||
| 21 | |||
| 22 | } // namespace Common | ||
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 90dfa22ca..631f64d05 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "common/logging/text_formatter.h" | 23 | #include "common/logging/text_formatter.h" |
| 24 | #include "common/string_util.h" | 24 | #include "common/string_util.h" |
| 25 | #include "common/threadsafe_queue.h" | 25 | #include "common/threadsafe_queue.h" |
| 26 | #include "core/settings.h" | ||
| 26 | 27 | ||
| 27 | namespace Log { | 28 | namespace Log { |
| 28 | 29 | ||
| @@ -152,10 +153,19 @@ FileBackend::FileBackend(const std::string& filename) | |||
| 152 | void FileBackend::Write(const Entry& entry) { | 153 | void FileBackend::Write(const Entry& entry) { |
| 153 | // prevent logs from going over the maximum size (in case its spamming and the user doesn't | 154 | // prevent logs from going over the maximum size (in case its spamming and the user doesn't |
| 154 | // know) | 155 | // know) |
| 155 | constexpr std::size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L; | 156 | constexpr std::size_t MAX_BYTES_WRITTEN = 100 * 1024 * 1024; |
| 156 | if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { | 157 | constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1024 * 1024 * 1024; |
| 158 | |||
| 159 | if (!file.IsOpen()) { | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN_EXTENDED) { | ||
| 164 | return; | ||
| 165 | } else if (!Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN) { | ||
| 157 | return; | 166 | return; |
| 158 | } | 167 | } |
| 168 | |||
| 159 | bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); | 169 | bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); |
| 160 | if (entry.log_level >= Level::Error) { | 170 | if (entry.log_level >= Level::Error) { |
| 161 | file.Flush(); | 171 | file.Flush(); |
| @@ -222,6 +232,7 @@ void DebuggerBackend::Write(const Entry& entry) { | |||
| 222 | SUB(Service, NPNS) \ | 232 | SUB(Service, NPNS) \ |
| 223 | SUB(Service, NS) \ | 233 | SUB(Service, NS) \ |
| 224 | SUB(Service, NVDRV) \ | 234 | SUB(Service, NVDRV) \ |
| 235 | SUB(Service, OLSC) \ | ||
| 225 | SUB(Service, PCIE) \ | 236 | SUB(Service, PCIE) \ |
| 226 | SUB(Service, PCTL) \ | 237 | SUB(Service, PCTL) \ |
| 227 | SUB(Service, PCV) \ | 238 | SUB(Service, PCV) \ |
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 13a4f1e30..835894918 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -95,6 +95,7 @@ enum class Class : ClassType { | |||
| 95 | Service_NPNS, ///< The NPNS service | 95 | Service_NPNS, ///< The NPNS service |
| 96 | Service_NS, ///< The NS services | 96 | Service_NS, ///< The NS services |
| 97 | Service_NVDRV, ///< The NVDRV (Nvidia driver) service | 97 | Service_NVDRV, ///< The NVDRV (Nvidia driver) service |
| 98 | Service_OLSC, ///< The OLSC service | ||
| 98 | Service_PCIE, ///< The PCIe service | 99 | Service_PCIE, ///< The PCIe service |
| 99 | Service_PCTL, ///< The PCTL (Parental control) service | 100 | Service_PCTL, ///< The PCTL (Parental control) service |
| 100 | Service_PCV, ///< The PCV service | 101 | Service_PCV, ///< The PCV service |
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index e5d3090d5..bccea0894 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp | |||
| @@ -8,7 +8,7 @@ namespace Common { | |||
| 8 | 8 | ||
| 9 | PageTable::PageTable() = default; | 9 | PageTable::PageTable() = default; |
| 10 | 10 | ||
| 11 | PageTable::~PageTable() = default; | 11 | PageTable::~PageTable() noexcept = default; |
| 12 | 12 | ||
| 13 | void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, | 13 | void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, |
| 14 | bool has_attribute) { | 14 | bool has_attribute) { |
diff --git a/src/common/page_table.h b/src/common/page_table.h index cf5eed780..9754fabf9 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | 7 | #include <tuple> |
| 8 | |||
| 9 | #include <boost/icl/interval_map.hpp> | ||
| 10 | 8 | ||
| 11 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 12 | #include "common/memory_hook.h" | 10 | #include "common/memory_hook.h" |
| @@ -51,13 +49,21 @@ struct SpecialRegion { | |||
| 51 | */ | 49 | */ |
| 52 | struct PageTable { | 50 | struct PageTable { |
| 53 | PageTable(); | 51 | PageTable(); |
| 54 | ~PageTable(); | 52 | ~PageTable() noexcept; |
| 53 | |||
| 54 | PageTable(const PageTable&) = delete; | ||
| 55 | PageTable& operator=(const PageTable&) = delete; | ||
| 56 | |||
| 57 | PageTable(PageTable&&) noexcept = default; | ||
| 58 | PageTable& operator=(PageTable&&) noexcept = default; | ||
| 55 | 59 | ||
| 56 | /** | 60 | /** |
| 57 | * Resizes the page table to be able to accomodate enough pages within | 61 | * Resizes the page table to be able to accomodate enough pages within |
| 58 | * a given address space. | 62 | * a given address space. |
| 59 | * | 63 | * |
| 60 | * @param address_space_width_in_bits The address size width in bits. | 64 | * @param address_space_width_in_bits The address size width in bits. |
| 65 | * @param page_size_in_bits The page size in bits. | ||
| 66 | * @param has_attribute Whether or not this page has any backing attributes. | ||
| 61 | */ | 67 | */ |
| 62 | void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, | 68 | void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, |
| 63 | bool has_attribute); | 69 | bool has_attribute); |
diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp index b009cb500..e3ca29258 100644 --- a/src/common/virtual_buffer.cpp +++ b/src/common/virtual_buffer.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Common { | 14 | namespace Common { |
| 15 | 15 | ||
| 16 | void* AllocateMemoryPages(std::size_t size) { | 16 | void* AllocateMemoryPages(std::size_t size) noexcept { |
| 17 | #ifdef _WIN32 | 17 | #ifdef _WIN32 |
| 18 | void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)}; | 18 | void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)}; |
| 19 | #else | 19 | #else |
| @@ -29,7 +29,7 @@ void* AllocateMemoryPages(std::size_t size) { | |||
| 29 | return base; | 29 | return base; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) { | 32 | void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) noexcept { |
| 33 | if (!base) { | 33 | if (!base) { |
| 34 | return; | 34 | return; |
| 35 | } | 35 | } |
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h index 125cb42f0..91d430036 100644 --- a/src/common/virtual_buffer.h +++ b/src/common/virtual_buffer.h | |||
| @@ -4,29 +4,53 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_funcs.h" | 7 | #include <type_traits> |
| 8 | #include <utility> | ||
| 8 | 9 | ||
| 9 | namespace Common { | 10 | namespace Common { |
| 10 | 11 | ||
| 11 | void* AllocateMemoryPages(std::size_t size); | 12 | void* AllocateMemoryPages(std::size_t size) noexcept; |
| 12 | void FreeMemoryPages(void* base, std::size_t size); | 13 | void FreeMemoryPages(void* base, std::size_t size) noexcept; |
| 13 | 14 | ||
| 14 | template <typename T> | 15 | template <typename T> |
| 15 | class VirtualBuffer final : NonCopyable { | 16 | class VirtualBuffer final { |
| 16 | public: | 17 | public: |
| 18 | static_assert( | ||
| 19 | std::is_trivially_constructible_v<T>, | ||
| 20 | "T must be trivially constructible, as non-trivial constructors will not be executed " | ||
| 21 | "with the current allocator"); | ||
| 22 | |||
| 17 | constexpr VirtualBuffer() = default; | 23 | constexpr VirtualBuffer() = default; |
| 18 | explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} { | 24 | explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} { |
| 19 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); | 25 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); |
| 20 | } | 26 | } |
| 21 | 27 | ||
| 22 | ~VirtualBuffer() { | 28 | ~VirtualBuffer() noexcept { |
| 23 | FreeMemoryPages(base_ptr, alloc_size); | 29 | FreeMemoryPages(base_ptr, alloc_size); |
| 24 | } | 30 | } |
| 25 | 31 | ||
| 32 | VirtualBuffer(const VirtualBuffer&) = delete; | ||
| 33 | VirtualBuffer& operator=(const VirtualBuffer&) = delete; | ||
| 34 | |||
| 35 | VirtualBuffer(VirtualBuffer&& other) noexcept | ||
| 36 | : alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr), | ||
| 37 | nullptr} {} | ||
| 38 | |||
| 39 | VirtualBuffer& operator=(VirtualBuffer&& other) noexcept { | ||
| 40 | alloc_size = std::exchange(other.alloc_size, 0); | ||
| 41 | base_ptr = std::exchange(other.base_ptr, nullptr); | ||
| 42 | return *this; | ||
| 43 | } | ||
| 44 | |||
| 26 | void resize(std::size_t count) { | 45 | void resize(std::size_t count) { |
| 46 | const auto new_size = count * sizeof(T); | ||
| 47 | if (new_size == alloc_size) { | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | |||
| 27 | FreeMemoryPages(base_ptr, alloc_size); | 51 | FreeMemoryPages(base_ptr, alloc_size); |
| 28 | 52 | ||
| 29 | alloc_size = count * sizeof(T); | 53 | alloc_size = new_size; |
| 30 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); | 54 | base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); |
| 31 | } | 55 | } |
| 32 | 56 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a1d8dcfa5..e370fd225 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -458,6 +458,8 @@ add_library(core STATIC | |||
| 458 | hle/service/nvflinger/buffer_queue.h | 458 | hle/service/nvflinger/buffer_queue.h |
| 459 | hle/service/nvflinger/nvflinger.cpp | 459 | hle/service/nvflinger/nvflinger.cpp |
| 460 | hle/service/nvflinger/nvflinger.h | 460 | hle/service/nvflinger/nvflinger.h |
| 461 | hle/service/olsc/olsc.cpp | ||
| 462 | hle/service/olsc/olsc.h | ||
| 461 | hle/service/pcie/pcie.cpp | 463 | hle/service/pcie/pcie.cpp |
| 462 | hle/service/pcie/pcie.h | 464 | hle/service/pcie/pcie.h |
| 463 | hle/service/pctl/module.cpp | 465 | hle/service/pctl/module.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 242796008..7ca3652af 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -145,7 +145,7 @@ struct System::Impl { | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { | 147 | ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { |
| 148 | LOG_DEBUG(HW_Memory, "initialized OK"); | 148 | LOG_DEBUG(Core, "initialized OK"); |
| 149 | 149 | ||
| 150 | device_memory = std::make_unique<Core::DeviceMemory>(); | 150 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 151 | 151 | ||
| @@ -187,7 +187,7 @@ struct System::Impl { | |||
| 187 | 187 | ||
| 188 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); | 188 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); |
| 189 | 189 | ||
| 190 | Service::Init(service_manager, system); | 190 | services = std::make_unique<Service::Services>(service_manager, system); |
| 191 | GDBStub::DeferStart(); | 191 | GDBStub::DeferStart(); |
| 192 | 192 | ||
| 193 | interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system); | 193 | interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system); |
| @@ -208,9 +208,11 @@ struct System::Impl { | |||
| 208 | return ResultStatus::Success; | 208 | return ResultStatus::Success; |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, | 211 | ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, |
| 212 | const std::string& filepath) { | 212 | std::size_t program_index) { |
| 213 | app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); | 213 | app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), |
| 214 | program_index); | ||
| 215 | |||
| 214 | if (!app_loader) { | 216 | if (!app_loader) { |
| 215 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | 217 | LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); |
| 216 | return ResultStatus::ErrorGetLoader; | 218 | return ResultStatus::ErrorGetLoader; |
| @@ -224,7 +226,7 @@ struct System::Impl { | |||
| 224 | return init_result; | 226 | return init_result; |
| 225 | } | 227 | } |
| 226 | 228 | ||
| 227 | telemetry_session->AddInitialInfo(*app_loader); | 229 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |
| 228 | auto main_process = | 230 | auto main_process = |
| 229 | Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); | 231 | Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); |
| 230 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | 232 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |
| @@ -296,7 +298,7 @@ struct System::Impl { | |||
| 296 | 298 | ||
| 297 | // Shutdown emulation session | 299 | // Shutdown emulation session |
| 298 | GDBStub::Shutdown(); | 300 | GDBStub::Shutdown(); |
| 299 | Service::Shutdown(); | 301 | services.reset(); |
| 300 | service_manager.reset(); | 302 | service_manager.reset(); |
| 301 | cheat_engine.reset(); | 303 | cheat_engine.reset(); |
| 302 | telemetry_session.reset(); | 304 | telemetry_session.reset(); |
| @@ -306,8 +308,8 @@ struct System::Impl { | |||
| 306 | cpu_manager.Shutdown(); | 308 | cpu_manager.Shutdown(); |
| 307 | 309 | ||
| 308 | // Shutdown kernel and core timing | 310 | // Shutdown kernel and core timing |
| 309 | kernel.Shutdown(); | ||
| 310 | core_timing.Shutdown(); | 311 | core_timing.Shutdown(); |
| 312 | kernel.Shutdown(); | ||
| 311 | 313 | ||
| 312 | // Close app loader | 314 | // Close app loader |
| 313 | app_loader.reset(); | 315 | app_loader.reset(); |
| @@ -338,7 +340,7 @@ struct System::Impl { | |||
| 338 | Service::Glue::ApplicationLaunchProperty launch{}; | 340 | Service::Glue::ApplicationLaunchProperty launch{}; |
| 339 | launch.title_id = process.GetTitleID(); | 341 | launch.title_id = process.GetTitleID(); |
| 340 | 342 | ||
| 341 | FileSys::PatchManager pm{launch.title_id}; | 343 | FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider}; |
| 342 | launch.version = pm.GetGameVersion().value_or(0); | 344 | launch.version = pm.GetGameVersion().value_or(0); |
| 343 | 345 | ||
| 344 | // TODO(DarkLordZach): When FSController/Game Card Support is added, if | 346 | // TODO(DarkLordZach): When FSController/Game Card Support is added, if |
| @@ -398,6 +400,9 @@ struct System::Impl { | |||
| 398 | /// Service manager | 400 | /// Service manager |
| 399 | std::shared_ptr<Service::SM::ServiceManager> service_manager; | 401 | std::shared_ptr<Service::SM::ServiceManager> service_manager; |
| 400 | 402 | ||
| 403 | /// Services | ||
| 404 | std::unique_ptr<Service::Services> services; | ||
| 405 | |||
| 401 | /// Telemetry session for this emulation session | 406 | /// Telemetry session for this emulation session |
| 402 | std::unique_ptr<Core::TelemetrySession> telemetry_session; | 407 | std::unique_ptr<Core::TelemetrySession> telemetry_session; |
| 403 | 408 | ||
| @@ -413,6 +418,8 @@ struct System::Impl { | |||
| 413 | bool is_multicore{}; | 418 | bool is_multicore{}; |
| 414 | bool is_async_gpu{}; | 419 | bool is_async_gpu{}; |
| 415 | 420 | ||
| 421 | ExecuteProgramCallback execute_program_callback; | ||
| 422 | |||
| 416 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | 423 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; |
| 417 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; | 424 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; |
| 418 | }; | 425 | }; |
| @@ -444,8 +451,13 @@ void System::InvalidateCpuInstructionCaches() { | |||
| 444 | impl->kernel.InvalidateAllInstructionCaches(); | 451 | impl->kernel.InvalidateAllInstructionCaches(); |
| 445 | } | 452 | } |
| 446 | 453 | ||
| 447 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { | 454 | void System::Shutdown() { |
| 448 | return impl->Load(*this, emu_window, filepath); | 455 | impl->Shutdown(); |
| 456 | } | ||
| 457 | |||
| 458 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, | ||
| 459 | std::size_t program_index) { | ||
| 460 | return impl->Load(*this, emu_window, filepath, program_index); | ||
| 449 | } | 461 | } |
| 450 | 462 | ||
| 451 | bool System::IsPoweredOn() const { | 463 | bool System::IsPoweredOn() const { |
| @@ -632,7 +644,11 @@ const std::string& System::GetStatusDetails() const { | |||
| 632 | return impl->status_details; | 644 | return impl->status_details; |
| 633 | } | 645 | } |
| 634 | 646 | ||
| 635 | Loader::AppLoader& System::GetAppLoader() const { | 647 | Loader::AppLoader& System::GetAppLoader() { |
| 648 | return *impl->app_loader; | ||
| 649 | } | ||
| 650 | |||
| 651 | const Loader::AppLoader& System::GetAppLoader() const { | ||
| 636 | return *impl->app_loader; | 652 | return *impl->app_loader; |
| 637 | } | 653 | } |
| 638 | 654 | ||
| @@ -748,14 +764,6 @@ const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const { | |||
| 748 | return impl->build_id; | 764 | return impl->build_id; |
| 749 | } | 765 | } |
| 750 | 766 | ||
| 751 | System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | ||
| 752 | return impl->Init(*this, emu_window); | ||
| 753 | } | ||
| 754 | |||
| 755 | void System::Shutdown() { | ||
| 756 | impl->Shutdown(); | ||
| 757 | } | ||
| 758 | |||
| 759 | Service::SM::ServiceManager& System::ServiceManager() { | 767 | Service::SM::ServiceManager& System::ServiceManager() { |
| 760 | return *impl->service_manager; | 768 | return *impl->service_manager; |
| 761 | } | 769 | } |
| @@ -786,4 +794,16 @@ bool System::IsMulticore() const { | |||
| 786 | return impl->is_multicore; | 794 | return impl->is_multicore; |
| 787 | } | 795 | } |
| 788 | 796 | ||
| 797 | void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { | ||
| 798 | impl->execute_program_callback = std::move(callback); | ||
| 799 | } | ||
| 800 | |||
| 801 | void System::ExecuteProgram(std::size_t program_index) { | ||
| 802 | if (impl->execute_program_callback) { | ||
| 803 | impl->execute_program_callback(program_index); | ||
| 804 | } else { | ||
| 805 | LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend"); | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 789 | } // namespace Core | 809 | } // namespace Core |
diff --git a/src/core/core.h b/src/core/core.h index 6db896bae..f642befc0 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | 7 | #include <cstddef> |
| 8 | #include <functional> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <string> | 10 | #include <string> |
| 10 | #include <vector> | 11 | #include <vector> |
| @@ -144,19 +145,19 @@ public: | |||
| 144 | * Run the OS and Application | 145 | * Run the OS and Application |
| 145 | * This function will start emulation and run the relevant devices | 146 | * This function will start emulation and run the relevant devices |
| 146 | */ | 147 | */ |
| 147 | ResultStatus Run(); | 148 | [[nodiscard]] ResultStatus Run(); |
| 148 | 149 | ||
| 149 | /** | 150 | /** |
| 150 | * Pause the OS and Application | 151 | * Pause the OS and Application |
| 151 | * This function will pause emulation and stop the relevant devices | 152 | * This function will pause emulation and stop the relevant devices |
| 152 | */ | 153 | */ |
| 153 | ResultStatus Pause(); | 154 | [[nodiscard]] ResultStatus Pause(); |
| 154 | 155 | ||
| 155 | /** | 156 | /** |
| 156 | * Step the CPU one instruction | 157 | * Step the CPU one instruction |
| 157 | * @return Result status, indicating whether or not the operation succeeded. | 158 | * @return Result status, indicating whether or not the operation succeeded. |
| 158 | */ | 159 | */ |
| 159 | ResultStatus SingleStep(); | 160 | [[nodiscard]] ResultStatus SingleStep(); |
| 160 | 161 | ||
| 161 | /** | 162 | /** |
| 162 | * Invalidate the CPU instruction caches | 163 | * Invalidate the CPU instruction caches |
| @@ -173,22 +174,24 @@ public: | |||
| 173 | * @param emu_window Reference to the host-system window used for video output and keyboard | 174 | * @param emu_window Reference to the host-system window used for video output and keyboard |
| 174 | * input. | 175 | * input. |
| 175 | * @param filepath String path to the executable application to load on the host file system. | 176 | * @param filepath String path to the executable application to load on the host file system. |
| 177 | * @param program_index Specifies the index within the container of the program to launch. | ||
| 176 | * @returns ResultStatus code, indicating if the operation succeeded. | 178 | * @returns ResultStatus code, indicating if the operation succeeded. |
| 177 | */ | 179 | */ |
| 178 | ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath); | 180 | [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath, |
| 181 | std::size_t program_index = 0); | ||
| 179 | 182 | ||
| 180 | /** | 183 | /** |
| 181 | * Indicates if the emulated system is powered on (all subsystems initialized and able to run an | 184 | * Indicates if the emulated system is powered on (all subsystems initialized and able to run an |
| 182 | * application). | 185 | * application). |
| 183 | * @returns True if the emulated system is powered on, otherwise false. | 186 | * @returns True if the emulated system is powered on, otherwise false. |
| 184 | */ | 187 | */ |
| 185 | bool IsPoweredOn() const; | 188 | [[nodiscard]] bool IsPoweredOn() const; |
| 186 | 189 | ||
| 187 | /// Gets a reference to the telemetry session for this emulation session. | 190 | /// Gets a reference to the telemetry session for this emulation session. |
| 188 | Core::TelemetrySession& TelemetrySession(); | 191 | [[nodiscard]] Core::TelemetrySession& TelemetrySession(); |
| 189 | 192 | ||
| 190 | /// Gets a reference to the telemetry session for this emulation session. | 193 | /// Gets a reference to the telemetry session for this emulation session. |
| 191 | const Core::TelemetrySession& TelemetrySession() const; | 194 | [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; |
| 192 | 195 | ||
| 193 | /// Prepare the core emulation for a reschedule | 196 | /// Prepare the core emulation for a reschedule |
| 194 | void PrepareReschedule(); | 197 | void PrepareReschedule(); |
| @@ -197,185 +200,178 @@ public: | |||
| 197 | void PrepareReschedule(u32 core_index); | 200 | void PrepareReschedule(u32 core_index); |
| 198 | 201 | ||
| 199 | /// Gets and resets core performance statistics | 202 | /// Gets and resets core performance statistics |
| 200 | PerfStatsResults GetAndResetPerfStats(); | 203 | [[nodiscard]] PerfStatsResults GetAndResetPerfStats(); |
| 201 | 204 | ||
| 202 | /// Gets an ARM interface to the CPU core that is currently running | 205 | /// Gets an ARM interface to the CPU core that is currently running |
| 203 | ARM_Interface& CurrentArmInterface(); | 206 | [[nodiscard]] ARM_Interface& CurrentArmInterface(); |
| 204 | 207 | ||
| 205 | /// Gets an ARM interface to the CPU core that is currently running | 208 | /// Gets an ARM interface to the CPU core that is currently running |
| 206 | const ARM_Interface& CurrentArmInterface() const; | 209 | [[nodiscard]] const ARM_Interface& CurrentArmInterface() const; |
| 207 | 210 | ||
| 208 | /// Gets the index of the currently running CPU core | 211 | /// Gets the index of the currently running CPU core |
| 209 | std::size_t CurrentCoreIndex() const; | 212 | [[nodiscard]] std::size_t CurrentCoreIndex() const; |
| 210 | 213 | ||
| 211 | /// Gets the scheduler for the CPU core that is currently running | 214 | /// Gets the scheduler for the CPU core that is currently running |
| 212 | Kernel::Scheduler& CurrentScheduler(); | 215 | [[nodiscard]] Kernel::Scheduler& CurrentScheduler(); |
| 213 | 216 | ||
| 214 | /// Gets the scheduler for the CPU core that is currently running | 217 | /// Gets the scheduler for the CPU core that is currently running |
| 215 | const Kernel::Scheduler& CurrentScheduler() const; | 218 | [[nodiscard]] const Kernel::Scheduler& CurrentScheduler() const; |
| 216 | 219 | ||
| 217 | /// Gets the physical core for the CPU core that is currently running | 220 | /// Gets the physical core for the CPU core that is currently running |
| 218 | Kernel::PhysicalCore& CurrentPhysicalCore(); | 221 | [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); |
| 219 | 222 | ||
| 220 | /// Gets the physical core for the CPU core that is currently running | 223 | /// Gets the physical core for the CPU core that is currently running |
| 221 | const Kernel::PhysicalCore& CurrentPhysicalCore() const; | 224 | [[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const; |
| 222 | 225 | ||
| 223 | /// Gets a reference to an ARM interface for the CPU core with the specified index | 226 | /// Gets a reference to an ARM interface for the CPU core with the specified index |
| 224 | ARM_Interface& ArmInterface(std::size_t core_index); | 227 | [[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index); |
| 225 | 228 | ||
| 226 | /// Gets a const reference to an ARM interface from the CPU core with the specified index | 229 | /// Gets a const reference to an ARM interface from the CPU core with the specified index |
| 227 | const ARM_Interface& ArmInterface(std::size_t core_index) const; | 230 | [[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const; |
| 228 | 231 | ||
| 229 | CpuManager& GetCpuManager(); | 232 | /// Gets a reference to the underlying CPU manager. |
| 233 | [[nodiscard]] CpuManager& GetCpuManager(); | ||
| 230 | 234 | ||
| 231 | const CpuManager& GetCpuManager() const; | 235 | /// Gets a const reference to the underlying CPU manager |
| 236 | [[nodiscard]] const CpuManager& GetCpuManager() const; | ||
| 232 | 237 | ||
| 233 | /// Gets a reference to the exclusive monitor | 238 | /// Gets a reference to the exclusive monitor |
| 234 | ExclusiveMonitor& Monitor(); | 239 | [[nodiscard]] ExclusiveMonitor& Monitor(); |
| 235 | 240 | ||
| 236 | /// Gets a constant reference to the exclusive monitor | 241 | /// Gets a constant reference to the exclusive monitor |
| 237 | const ExclusiveMonitor& Monitor() const; | 242 | [[nodiscard]] const ExclusiveMonitor& Monitor() const; |
| 238 | 243 | ||
| 239 | /// Gets a mutable reference to the system memory instance. | 244 | /// Gets a mutable reference to the system memory instance. |
| 240 | Core::Memory::Memory& Memory(); | 245 | [[nodiscard]] Core::Memory::Memory& Memory(); |
| 241 | 246 | ||
| 242 | /// Gets a constant reference to the system memory instance. | 247 | /// Gets a constant reference to the system memory instance. |
| 243 | const Core::Memory::Memory& Memory() const; | 248 | [[nodiscard]] const Core::Memory::Memory& Memory() const; |
| 244 | 249 | ||
| 245 | /// Gets a mutable reference to the GPU interface | 250 | /// Gets a mutable reference to the GPU interface |
| 246 | Tegra::GPU& GPU(); | 251 | [[nodiscard]] Tegra::GPU& GPU(); |
| 247 | 252 | ||
| 248 | /// Gets an immutable reference to the GPU interface. | 253 | /// Gets an immutable reference to the GPU interface. |
| 249 | const Tegra::GPU& GPU() const; | 254 | [[nodiscard]] const Tegra::GPU& GPU() const; |
| 250 | 255 | ||
| 251 | /// Gets a mutable reference to the renderer. | 256 | /// Gets a mutable reference to the renderer. |
| 252 | VideoCore::RendererBase& Renderer(); | 257 | [[nodiscard]] VideoCore::RendererBase& Renderer(); |
| 253 | 258 | ||
| 254 | /// Gets an immutable reference to the renderer. | 259 | /// Gets an immutable reference to the renderer. |
| 255 | const VideoCore::RendererBase& Renderer() const; | 260 | [[nodiscard]] const VideoCore::RendererBase& Renderer() const; |
| 256 | 261 | ||
| 257 | /// Gets the scheduler for the CPU core with the specified index | 262 | /// Gets the scheduler for the CPU core with the specified index |
| 258 | Kernel::Scheduler& Scheduler(std::size_t core_index); | 263 | [[nodiscard]] Kernel::Scheduler& Scheduler(std::size_t core_index); |
| 259 | 264 | ||
| 260 | /// Gets the scheduler for the CPU core with the specified index | 265 | /// Gets the scheduler for the CPU core with the specified index |
| 261 | const Kernel::Scheduler& Scheduler(std::size_t core_index) const; | 266 | [[nodiscard]] const Kernel::Scheduler& Scheduler(std::size_t core_index) const; |
| 262 | 267 | ||
| 263 | /// Gets the global scheduler | 268 | /// Gets the global scheduler |
| 264 | Kernel::GlobalScheduler& GlobalScheduler(); | 269 | [[nodiscard]] Kernel::GlobalScheduler& GlobalScheduler(); |
| 265 | 270 | ||
| 266 | /// Gets the global scheduler | 271 | /// Gets the global scheduler |
| 267 | const Kernel::GlobalScheduler& GlobalScheduler() const; | 272 | [[nodiscard]] const Kernel::GlobalScheduler& GlobalScheduler() const; |
| 268 | 273 | ||
| 269 | /// Gets the manager for the guest device memory | 274 | /// Gets the manager for the guest device memory |
| 270 | Core::DeviceMemory& DeviceMemory(); | 275 | [[nodiscard]] Core::DeviceMemory& DeviceMemory(); |
| 271 | 276 | ||
| 272 | /// Gets the manager for the guest device memory | 277 | /// Gets the manager for the guest device memory |
| 273 | const Core::DeviceMemory& DeviceMemory() const; | 278 | [[nodiscard]] const Core::DeviceMemory& DeviceMemory() const; |
| 274 | 279 | ||
| 275 | /// Provides a pointer to the current process | 280 | /// Provides a pointer to the current process |
| 276 | Kernel::Process* CurrentProcess(); | 281 | [[nodiscard]] Kernel::Process* CurrentProcess(); |
| 277 | 282 | ||
| 278 | /// Provides a constant pointer to the current process. | 283 | /// Provides a constant pointer to the current process. |
| 279 | const Kernel::Process* CurrentProcess() const; | 284 | [[nodiscard]] const Kernel::Process* CurrentProcess() const; |
| 280 | 285 | ||
| 281 | /// Provides a reference to the core timing instance. | 286 | /// Provides a reference to the core timing instance. |
| 282 | Timing::CoreTiming& CoreTiming(); | 287 | [[nodiscard]] Timing::CoreTiming& CoreTiming(); |
| 283 | 288 | ||
| 284 | /// Provides a constant reference to the core timing instance. | 289 | /// Provides a constant reference to the core timing instance. |
| 285 | const Timing::CoreTiming& CoreTiming() const; | 290 | [[nodiscard]] const Timing::CoreTiming& CoreTiming() const; |
| 286 | 291 | ||
| 287 | /// Provides a reference to the interrupt manager instance. | 292 | /// Provides a reference to the interrupt manager instance. |
| 288 | Core::Hardware::InterruptManager& InterruptManager(); | 293 | [[nodiscard]] Core::Hardware::InterruptManager& InterruptManager(); |
| 289 | 294 | ||
| 290 | /// Provides a constant reference to the interrupt manager instance. | 295 | /// Provides a constant reference to the interrupt manager instance. |
| 291 | const Core::Hardware::InterruptManager& InterruptManager() const; | 296 | [[nodiscard]] const Core::Hardware::InterruptManager& InterruptManager() const; |
| 292 | 297 | ||
| 293 | /// Provides a reference to the kernel instance. | 298 | /// Provides a reference to the kernel instance. |
| 294 | Kernel::KernelCore& Kernel(); | 299 | [[nodiscard]] Kernel::KernelCore& Kernel(); |
| 295 | 300 | ||
| 296 | /// Provides a constant reference to the kernel instance. | 301 | /// Provides a constant reference to the kernel instance. |
| 297 | const Kernel::KernelCore& Kernel() const; | 302 | [[nodiscard]] const Kernel::KernelCore& Kernel() const; |
| 298 | 303 | ||
| 299 | /// Provides a reference to the internal PerfStats instance. | 304 | /// Provides a reference to the internal PerfStats instance. |
| 300 | Core::PerfStats& GetPerfStats(); | 305 | [[nodiscard]] Core::PerfStats& GetPerfStats(); |
| 301 | 306 | ||
| 302 | /// Provides a constant reference to the internal PerfStats instance. | 307 | /// Provides a constant reference to the internal PerfStats instance. |
| 303 | const Core::PerfStats& GetPerfStats() const; | 308 | [[nodiscard]] const Core::PerfStats& GetPerfStats() const; |
| 304 | 309 | ||
| 305 | /// Provides a reference to the frame limiter; | 310 | /// Provides a reference to the frame limiter; |
| 306 | Core::FrameLimiter& FrameLimiter(); | 311 | [[nodiscard]] Core::FrameLimiter& FrameLimiter(); |
| 307 | 312 | ||
| 308 | /// Provides a constant referent to the frame limiter | 313 | /// Provides a constant referent to the frame limiter |
| 309 | const Core::FrameLimiter& FrameLimiter() const; | 314 | [[nodiscard]] const Core::FrameLimiter& FrameLimiter() const; |
| 310 | 315 | ||
| 311 | /// Gets the name of the current game | 316 | /// Gets the name of the current game |
| 312 | Loader::ResultStatus GetGameName(std::string& out) const; | 317 | [[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const; |
| 313 | 318 | ||
| 314 | void SetStatus(ResultStatus new_status, const char* details); | 319 | void SetStatus(ResultStatus new_status, const char* details); |
| 315 | 320 | ||
| 316 | const std::string& GetStatusDetails() const; | 321 | [[nodiscard]] const std::string& GetStatusDetails() const; |
| 317 | 322 | ||
| 318 | Loader::AppLoader& GetAppLoader() const; | 323 | [[nodiscard]] Loader::AppLoader& GetAppLoader(); |
| 324 | [[nodiscard]] const Loader::AppLoader& GetAppLoader() const; | ||
| 319 | 325 | ||
| 320 | Service::SM::ServiceManager& ServiceManager(); | 326 | [[nodiscard]] Service::SM::ServiceManager& ServiceManager(); |
| 321 | const Service::SM::ServiceManager& ServiceManager() const; | 327 | [[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const; |
| 322 | 328 | ||
| 323 | void SetFilesystem(FileSys::VirtualFilesystem vfs); | 329 | void SetFilesystem(FileSys::VirtualFilesystem vfs); |
| 324 | 330 | ||
| 325 | FileSys::VirtualFilesystem GetFilesystem() const; | 331 | [[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const; |
| 326 | 332 | ||
| 327 | void RegisterCheatList(const std::vector<Memory::CheatEntry>& list, | 333 | void RegisterCheatList(const std::vector<Memory::CheatEntry>& list, |
| 328 | const std::array<u8, 0x20>& build_id, VAddr main_region_begin, | 334 | const std::array<u8, 0x20>& build_id, VAddr main_region_begin, |
| 329 | u64 main_region_size); | 335 | u64 main_region_size); |
| 330 | 336 | ||
| 331 | void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); | 337 | void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); |
| 332 | |||
| 333 | void SetDefaultAppletFrontendSet(); | 338 | void SetDefaultAppletFrontendSet(); |
| 334 | 339 | ||
| 335 | Service::AM::Applets::AppletManager& GetAppletManager(); | 340 | [[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager(); |
| 336 | 341 | [[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const; | |
| 337 | const Service::AM::Applets::AppletManager& GetAppletManager() const; | ||
| 338 | 342 | ||
| 339 | void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); | 343 | void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); |
| 340 | 344 | ||
| 341 | FileSys::ContentProvider& GetContentProvider(); | 345 | [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); |
| 342 | 346 | [[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const; | |
| 343 | const FileSys::ContentProvider& GetContentProvider() const; | ||
| 344 | 347 | ||
| 345 | Service::FileSystem::FileSystemController& GetFileSystemController(); | 348 | [[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController(); |
| 346 | 349 | [[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const; | |
| 347 | const Service::FileSystem::FileSystemController& GetFileSystemController() const; | ||
| 348 | 350 | ||
| 349 | void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot, | 351 | void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot, |
| 350 | FileSys::ContentProvider* provider); | 352 | FileSys::ContentProvider* provider); |
| 351 | 353 | ||
| 352 | void ClearContentProvider(FileSys::ContentProviderUnionSlot slot); | 354 | void ClearContentProvider(FileSys::ContentProviderUnionSlot slot); |
| 353 | 355 | ||
| 354 | const Reporter& GetReporter() const; | 356 | [[nodiscard]] const Reporter& GetReporter() const; |
| 355 | |||
| 356 | Service::Glue::ARPManager& GetARPManager(); | ||
| 357 | 357 | ||
| 358 | const Service::Glue::ARPManager& GetARPManager() const; | 358 | [[nodiscard]] Service::Glue::ARPManager& GetARPManager(); |
| 359 | [[nodiscard]] const Service::Glue::ARPManager& GetARPManager() const; | ||
| 359 | 360 | ||
| 360 | Service::APM::Controller& GetAPMController(); | 361 | [[nodiscard]] Service::APM::Controller& GetAPMController(); |
| 362 | [[nodiscard]] const Service::APM::Controller& GetAPMController() const; | ||
| 361 | 363 | ||
| 362 | const Service::APM::Controller& GetAPMController() const; | 364 | [[nodiscard]] Service::LM::Manager& GetLogManager(); |
| 365 | [[nodiscard]] const Service::LM::Manager& GetLogManager() const; | ||
| 363 | 366 | ||
| 364 | Service::LM::Manager& GetLogManager(); | 367 | [[nodiscard]] Service::Time::TimeManager& GetTimeManager(); |
| 365 | 368 | [[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const; | |
| 366 | const Service::LM::Manager& GetLogManager() const; | ||
| 367 | |||
| 368 | Service::Time::TimeManager& GetTimeManager(); | ||
| 369 | |||
| 370 | const Service::Time::TimeManager& GetTimeManager() const; | ||
| 371 | 369 | ||
| 372 | void SetExitLock(bool locked); | 370 | void SetExitLock(bool locked); |
| 373 | 371 | [[nodiscard]] bool GetExitLock() const; | |
| 374 | bool GetExitLock() const; | ||
| 375 | 372 | ||
| 376 | void SetCurrentProcessBuildID(const CurrentBuildProcessID& id); | 373 | void SetCurrentProcessBuildID(const CurrentBuildProcessID& id); |
| 377 | 374 | [[nodiscard]] const CurrentBuildProcessID& GetCurrentProcessBuildID() const; | |
| 378 | const CurrentBuildProcessID& GetCurrentProcessBuildID() const; | ||
| 379 | 375 | ||
| 380 | /// Register a host thread as an emulated CPU Core. | 376 | /// Register a host thread as an emulated CPU Core. |
| 381 | void RegisterCoreThread(std::size_t id); | 377 | void RegisterCoreThread(std::size_t id); |
| @@ -390,18 +386,27 @@ public: | |||
| 390 | void ExitDynarmicProfile(); | 386 | void ExitDynarmicProfile(); |
| 391 | 387 | ||
| 392 | /// Tells if system is running on multicore. | 388 | /// Tells if system is running on multicore. |
| 393 | bool IsMulticore() const; | 389 | [[nodiscard]] bool IsMulticore() const; |
| 394 | 390 | ||
| 395 | private: | 391 | /// Type used for the frontend to designate a callback for System to re-launch the application |
| 396 | System(); | 392 | /// using a specified program index. |
| 393 | using ExecuteProgramCallback = std::function<void(std::size_t)>; | ||
| 397 | 394 | ||
| 398 | /** | 395 | /** |
| 399 | * Initialize the emulated system. | 396 | * Registers a callback from the frontend for System to re-launch the application using a |
| 400 | * @param emu_window Reference to the host-system window used for video output and keyboard | 397 | * specified program index. |
| 401 | * input. | 398 | * @param callback Callback from the frontend to relaunch the application. |
| 402 | * @return ResultStatus code, indicating if the operation succeeded. | 399 | */ |
| 400 | void RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback); | ||
| 401 | |||
| 402 | /** | ||
| 403 | * Instructs the frontend to re-launch the application using the specified program_index. | ||
| 404 | * @param program_index Specifies the index within the application of the program to launch. | ||
| 403 | */ | 405 | */ |
| 404 | ResultStatus Init(Frontend::EmuWindow& emu_window); | 406 | void ExecuteProgram(std::size_t program_index); |
| 407 | |||
| 408 | private: | ||
| 409 | System(); | ||
| 405 | 410 | ||
| 406 | struct Impl; | 411 | struct Impl; |
| 407 | std::unique_ptr<Impl> impl; | 412 | std::unique_ptr<Impl> impl; |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 983210197..100e90d82 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/fiber.h" | 5 | #include "common/fiber.h" |
| 6 | #include "common/microprofile.h" | 6 | #include "common/microprofile.h" |
| 7 | #include "common/scope_exit.h" | ||
| 7 | #include "common/thread.h" | 8 | #include "common/thread.h" |
| 8 | #include "core/arm/exclusive_monitor.h" | 9 | #include "core/arm/exclusive_monitor.h" |
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| @@ -343,6 +344,16 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 343 | data.initialized = true; | 344 | data.initialized = true; |
| 344 | const bool sc_sync = !is_async_gpu && !is_multicore; | 345 | const bool sc_sync = !is_async_gpu && !is_multicore; |
| 345 | bool sc_sync_first_use = sc_sync; | 346 | bool sc_sync_first_use = sc_sync; |
| 347 | |||
| 348 | // Cleanup | ||
| 349 | SCOPE_EXIT({ | ||
| 350 | data.host_context->Exit(); | ||
| 351 | data.enter_barrier.reset(); | ||
| 352 | data.exit_barrier.reset(); | ||
| 353 | data.initialized = false; | ||
| 354 | MicroProfileOnThreadExit(); | ||
| 355 | }); | ||
| 356 | |||
| 346 | /// Running | 357 | /// Running |
| 347 | while (running_mode) { | 358 | while (running_mode) { |
| 348 | data.is_running = false; | 359 | data.is_running = false; |
| @@ -351,6 +362,12 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 351 | system.GPU().ObtainContext(); | 362 | system.GPU().ObtainContext(); |
| 352 | sc_sync_first_use = false; | 363 | sc_sync_first_use = false; |
| 353 | } | 364 | } |
| 365 | |||
| 366 | // Abort if emulation was killed before the session really starts | ||
| 367 | if (!system.IsPoweredOn()) { | ||
| 368 | return; | ||
| 369 | } | ||
| 370 | |||
| 354 | auto& scheduler = system.Kernel().CurrentScheduler(); | 371 | auto& scheduler = system.Kernel().CurrentScheduler(); |
| 355 | Kernel::Thread* current_thread = scheduler.GetCurrentThread(); | 372 | Kernel::Thread* current_thread = scheduler.GetCurrentThread(); |
| 356 | data.is_running = true; | 373 | data.is_running = true; |
| @@ -360,13 +377,6 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 360 | data.exit_barrier->Wait(); | 377 | data.exit_barrier->Wait(); |
| 361 | data.is_paused = false; | 378 | data.is_paused = false; |
| 362 | } | 379 | } |
| 363 | /// Time to cleanup | ||
| 364 | data.host_context->Exit(); | ||
| 365 | data.enter_barrier.reset(); | ||
| 366 | data.exit_barrier.reset(); | ||
| 367 | data.initialized = false; | ||
| 368 | |||
| 369 | MicroProfileOnThreadExit(); | ||
| 370 | } | 380 | } |
| 371 | 381 | ||
| 372 | } // namespace Core | 382 | } // namespace Core |
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 956da68f7..8dee5590b 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -29,7 +29,7 @@ constexpr std::array partition_names{ | |||
| 29 | "logo", | 29 | "logo", |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | XCI::XCI(VirtualFile file_) | 32 | XCI::XCI(VirtualFile file_, std::size_t program_index) |
| 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, | 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, |
| 34 | partitions(partition_names.size()), | 34 | partitions(partition_names.size()), |
| 35 | partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { | 35 | partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { |
| @@ -62,7 +62,8 @@ XCI::XCI(VirtualFile file_) | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | secure_partition = std::make_shared<NSP>( | 64 | secure_partition = std::make_shared<NSP>( |
| 65 | main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)])); | 65 | main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), |
| 66 | program_index); | ||
| 66 | 67 | ||
| 67 | ncas = secure_partition->GetNCAsCollapsed(); | 68 | ncas = secure_partition->GetNCAsCollapsed(); |
| 68 | program = | 69 | program = |
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 2d0a0f285..4960e90fe 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h | |||
| @@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo }; | |||
| 78 | 78 | ||
| 79 | class XCI : public ReadOnlyVfsDirectory { | 79 | class XCI : public ReadOnlyVfsDirectory { |
| 80 | public: | 80 | public: |
| 81 | explicit XCI(VirtualFile file); | 81 | explicit XCI(VirtualFile file, std::size_t program_index = 0); |
| 82 | ~XCI() override; | 82 | ~XCI() override; |
| 83 | 83 | ||
| 84 | Loader::ResultStatus GetStatus() const; | 84 | Loader::ResultStatus GetStatus() const; |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 807b05821..e9d1607d0 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -112,7 +112,10 @@ bool IsDirValidAndNonEmpty(const VirtualDir& dir) { | |||
| 112 | } | 112 | } |
| 113 | } // Anonymous namespace | 113 | } // Anonymous namespace |
| 114 | 114 | ||
| 115 | PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} | 115 | PatchManager::PatchManager(u64 title_id_, |
| 116 | const Service::FileSystem::FileSystemController& fs_controller_, | ||
| 117 | const ContentProvider& content_provider_) | ||
| 118 | : title_id{title_id_}, fs_controller{fs_controller_}, content_provider{content_provider_} {} | ||
| 116 | 119 | ||
| 117 | PatchManager::~PatchManager() = default; | 120 | PatchManager::~PatchManager() = default; |
| 118 | 121 | ||
| @@ -128,34 +131,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 128 | 131 | ||
| 129 | if (Settings::values.dump_exefs) { | 132 | if (Settings::values.dump_exefs) { |
| 130 | LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); | 133 | LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); |
| 131 | const auto dump_dir = | 134 | const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id); |
| 132 | Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id); | ||
| 133 | if (dump_dir != nullptr) { | 135 | if (dump_dir != nullptr) { |
| 134 | const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); | 136 | const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); |
| 135 | VfsRawCopyD(exefs, exefs_dir); | 137 | VfsRawCopyD(exefs, exefs_dir); |
| 136 | } | 138 | } |
| 137 | } | 139 | } |
| 138 | 140 | ||
| 139 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | ||
| 140 | |||
| 141 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 141 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 142 | const auto update_disabled = | 142 | const auto update_disabled = |
| 143 | std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); | 143 | std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); |
| 144 | 144 | ||
| 145 | // Game Updates | 145 | // Game Updates |
| 146 | const auto update_tid = GetUpdateTitleID(title_id); | 146 | const auto update_tid = GetUpdateTitleID(title_id); |
| 147 | const auto update = installed.GetEntry(update_tid, ContentRecordType::Program); | 147 | const auto update = content_provider.GetEntry(update_tid, ContentRecordType::Program); |
| 148 | 148 | ||
| 149 | if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr && | 149 | if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr && |
| 150 | update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | 150 | update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { |
| 151 | LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", | 151 | LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", |
| 152 | FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); | 152 | FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0))); |
| 153 | exefs = update->GetExeFS(); | 153 | exefs = update->GetExeFS(); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | // LayeredExeFS | 156 | // LayeredExeFS |
| 157 | const auto load_dir = | 157 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 158 | Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); | ||
| 159 | if (load_dir != nullptr && load_dir->GetSize() > 0) { | 158 | if (load_dir != nullptr && load_dir->GetSize() > 0) { |
| 160 | auto patch_dirs = load_dir->GetSubdirectories(); | 159 | auto patch_dirs = load_dir->GetSubdirectories(); |
| 161 | std::sort( | 160 | std::sort( |
| @@ -241,8 +240,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st | |||
| 241 | if (Settings::values.dump_nso) { | 240 | if (Settings::values.dump_nso) { |
| 242 | LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id, | 241 | LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id, |
| 243 | title_id); | 242 | title_id); |
| 244 | const auto dump_dir = | 243 | const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id); |
| 245 | Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id); | ||
| 246 | if (dump_dir != nullptr) { | 244 | if (dump_dir != nullptr) { |
| 247 | const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso"); | 245 | const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso"); |
| 248 | const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id)); | 246 | const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id)); |
| @@ -254,8 +252,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st | |||
| 254 | 252 | ||
| 255 | LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id); | 253 | LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id); |
| 256 | 254 | ||
| 257 | const auto load_dir = | 255 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 258 | Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); | ||
| 259 | if (load_dir == nullptr) { | 256 | if (load_dir == nullptr) { |
| 260 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); | 257 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); |
| 261 | return nso; | 258 | return nso; |
| @@ -298,8 +295,7 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const { | |||
| 298 | 295 | ||
| 299 | LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id); | 296 | LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id); |
| 300 | 297 | ||
| 301 | const auto load_dir = | 298 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 302 | Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); | ||
| 303 | if (load_dir == nullptr) { | 299 | if (load_dir == nullptr) { |
| 304 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); | 300 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); |
| 305 | return false; | 301 | return false; |
| @@ -313,8 +309,8 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const { | |||
| 313 | } | 309 | } |
| 314 | 310 | ||
| 315 | std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( | 311 | std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( |
| 316 | const Core::System& system, const BuildID& build_id_) const { | 312 | const BuildID& build_id_) const { |
| 317 | const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id); | 313 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 318 | if (load_dir == nullptr) { | 314 | if (load_dir == nullptr) { |
| 319 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); | 315 | LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); |
| 320 | return {}; | 316 | return {}; |
| @@ -347,9 +343,9 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( | |||
| 347 | return out; | 343 | return out; |
| 348 | } | 344 | } |
| 349 | 345 | ||
| 350 | static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { | 346 | static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type, |
| 351 | const auto load_dir = | 347 | const Service::FileSystem::FileSystemController& fs_controller) { |
| 352 | Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); | 348 | const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 353 | if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || | 349 | if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || |
| 354 | load_dir == nullptr || load_dir->GetSize() <= 0) { | 350 | load_dir == nullptr || load_dir->GetSize() <= 0) { |
| 355 | return; | 351 | return; |
| @@ -411,19 +407,19 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content | |||
| 411 | const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}", | 407 | const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}", |
| 412 | title_id, static_cast<u8>(type)); | 408 | title_id, static_cast<u8>(type)); |
| 413 | 409 | ||
| 414 | if (type == ContentRecordType::Program || type == ContentRecordType::Data) | 410 | if (type == ContentRecordType::Program || type == ContentRecordType::Data) { |
| 415 | LOG_INFO(Loader, "{}", log_string); | 411 | LOG_INFO(Loader, "{}", log_string); |
| 416 | else | 412 | } else { |
| 417 | LOG_DEBUG(Loader, "{}", log_string); | 413 | LOG_DEBUG(Loader, "{}", log_string); |
| 414 | } | ||
| 418 | 415 | ||
| 419 | if (romfs == nullptr) | 416 | if (romfs == nullptr) { |
| 420 | return romfs; | 417 | return romfs; |
| 421 | 418 | } | |
| 422 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | ||
| 423 | 419 | ||
| 424 | // Game Updates | 420 | // Game Updates |
| 425 | const auto update_tid = GetUpdateTitleID(title_id); | 421 | const auto update_tid = GetUpdateTitleID(title_id); |
| 426 | const auto update = installed.GetEntryRaw(update_tid, type); | 422 | const auto update = content_provider.GetEntryRaw(update_tid, type); |
| 427 | 423 | ||
| 428 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 424 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 429 | const auto update_disabled = | 425 | const auto update_disabled = |
| @@ -434,7 +430,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content | |||
| 434 | if (new_nca->GetStatus() == Loader::ResultStatus::Success && | 430 | if (new_nca->GetStatus() == Loader::ResultStatus::Success && |
| 435 | new_nca->GetRomFS() != nullptr) { | 431 | new_nca->GetRomFS() != nullptr) { |
| 436 | LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", | 432 | LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", |
| 437 | FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); | 433 | FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0))); |
| 438 | romfs = new_nca->GetRomFS(); | 434 | romfs = new_nca->GetRomFS(); |
| 439 | } | 435 | } |
| 440 | } else if (!update_disabled && update_raw != nullptr) { | 436 | } else if (!update_disabled && update_raw != nullptr) { |
| @@ -447,7 +443,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content | |||
| 447 | } | 443 | } |
| 448 | 444 | ||
| 449 | // LayeredFS | 445 | // LayeredFS |
| 450 | ApplyLayeredFS(romfs, title_id, type); | 446 | ApplyLayeredFS(romfs, title_id, type, fs_controller); |
| 451 | 447 | ||
| 452 | return romfs; | 448 | return romfs; |
| 453 | } | 449 | } |
| @@ -458,12 +454,11 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 458 | } | 454 | } |
| 459 | 455 | ||
| 460 | std::map<std::string, std::string, std::less<>> out; | 456 | std::map<std::string, std::string, std::less<>> out; |
| 461 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | ||
| 462 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 457 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 463 | 458 | ||
| 464 | // Game Updates | 459 | // Game Updates |
| 465 | const auto update_tid = GetUpdateTitleID(title_id); | 460 | const auto update_tid = GetUpdateTitleID(title_id); |
| 466 | PatchManager update{update_tid}; | 461 | PatchManager update{update_tid, fs_controller, content_provider}; |
| 467 | const auto metadata = update.GetControlMetadata(); | 462 | const auto metadata = update.GetControlMetadata(); |
| 468 | const auto& nacp = metadata.first; | 463 | const auto& nacp = metadata.first; |
| 469 | 464 | ||
| @@ -474,8 +469,8 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 474 | if (nacp != nullptr) { | 469 | if (nacp != nullptr) { |
| 475 | out.insert_or_assign(update_label, nacp->GetVersionString()); | 470 | out.insert_or_assign(update_label, nacp->GetVersionString()); |
| 476 | } else { | 471 | } else { |
| 477 | if (installed.HasEntry(update_tid, ContentRecordType::Program)) { | 472 | if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { |
| 478 | const auto meta_ver = installed.GetEntryVersion(update_tid); | 473 | const auto meta_ver = content_provider.GetEntryVersion(update_tid); |
| 479 | if (meta_ver.value_or(0) == 0) { | 474 | if (meta_ver.value_or(0) == 0) { |
| 480 | out.insert_or_assign(update_label, ""); | 475 | out.insert_or_assign(update_label, ""); |
| 481 | } else { | 476 | } else { |
| @@ -487,8 +482,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 487 | } | 482 | } |
| 488 | 483 | ||
| 489 | // General Mods (LayeredFS and IPS) | 484 | // General Mods (LayeredFS and IPS) |
| 490 | const auto mod_dir = | 485 | const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); |
| 491 | Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); | ||
| 492 | if (mod_dir != nullptr && mod_dir->GetSize() > 0) { | 486 | if (mod_dir != nullptr && mod_dir->GetSize() > 0) { |
| 493 | for (const auto& mod : mod_dir->GetSubdirectories()) { | 487 | for (const auto& mod : mod_dir->GetSubdirectories()) { |
| 494 | std::string types; | 488 | std::string types; |
| @@ -532,13 +526,15 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 532 | } | 526 | } |
| 533 | 527 | ||
| 534 | // DLC | 528 | // DLC |
| 535 | const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); | 529 | const auto dlc_entries = |
| 530 | content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); | ||
| 536 | std::vector<ContentProviderEntry> dlc_match; | 531 | std::vector<ContentProviderEntry> dlc_match; |
| 537 | dlc_match.reserve(dlc_entries.size()); | 532 | dlc_match.reserve(dlc_entries.size()); |
| 538 | std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), | 533 | std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), |
| 539 | [this, &installed](const ContentProviderEntry& entry) { | 534 | [this](const ContentProviderEntry& entry) { |
| 540 | return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && | 535 | return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && |
| 541 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; | 536 | content_provider.GetEntry(entry)->GetStatus() == |
| 537 | Loader::ResultStatus::Success; | ||
| 542 | }); | 538 | }); |
| 543 | if (!dlc_match.empty()) { | 539 | if (!dlc_match.empty()) { |
| 544 | // Ensure sorted so DLC IDs show in order. | 540 | // Ensure sorted so DLC IDs show in order. |
| @@ -559,19 +555,16 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 559 | } | 555 | } |
| 560 | 556 | ||
| 561 | std::optional<u32> PatchManager::GetGameVersion() const { | 557 | std::optional<u32> PatchManager::GetGameVersion() const { |
| 562 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | ||
| 563 | const auto update_tid = GetUpdateTitleID(title_id); | 558 | const auto update_tid = GetUpdateTitleID(title_id); |
| 564 | if (installed.HasEntry(update_tid, ContentRecordType::Program)) { | 559 | if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { |
| 565 | return installed.GetEntryVersion(update_tid); | 560 | return content_provider.GetEntryVersion(update_tid); |
| 566 | } | 561 | } |
| 567 | 562 | ||
| 568 | return installed.GetEntryVersion(title_id); | 563 | return content_provider.GetEntryVersion(title_id); |
| 569 | } | 564 | } |
| 570 | 565 | ||
| 571 | PatchManager::Metadata PatchManager::GetControlMetadata() const { | 566 | PatchManager::Metadata PatchManager::GetControlMetadata() const { |
| 572 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | 567 | const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control); |
| 573 | |||
| 574 | const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control); | ||
| 575 | if (base_control_nca == nullptr) { | 568 | if (base_control_nca == nullptr) { |
| 576 | return {}; | 569 | return {}; |
| 577 | } | 570 | } |
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 1f28c6241..fb1853035 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h | |||
| @@ -17,8 +17,13 @@ namespace Core { | |||
| 17 | class System; | 17 | class System; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | namespace Service::FileSystem { | ||
| 21 | class FileSystemController; | ||
| 22 | } | ||
| 23 | |||
| 20 | namespace FileSys { | 24 | namespace FileSys { |
| 21 | 25 | ||
| 26 | class ContentProvider; | ||
| 22 | class NCA; | 27 | class NCA; |
| 23 | class NACP; | 28 | class NACP; |
| 24 | 29 | ||
| @@ -29,7 +34,9 @@ public: | |||
| 29 | using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; | 34 | using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; |
| 30 | using PatchVersionNames = std::map<std::string, std::string, std::less<>>; | 35 | using PatchVersionNames = std::map<std::string, std::string, std::less<>>; |
| 31 | 36 | ||
| 32 | explicit PatchManager(u64 title_id); | 37 | explicit PatchManager(u64 title_id_, |
| 38 | const Service::FileSystem::FileSystemController& fs_controller_, | ||
| 39 | const ContentProvider& content_provider_); | ||
| 33 | ~PatchManager(); | 40 | ~PatchManager(); |
| 34 | 41 | ||
| 35 | [[nodiscard]] u64 GetTitleID() const; | 42 | [[nodiscard]] u64 GetTitleID() const; |
| @@ -50,7 +57,7 @@ public: | |||
| 50 | 57 | ||
| 51 | // Creates a CheatList object with all | 58 | // Creates a CheatList object with all |
| 52 | [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList( | 59 | [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList( |
| 53 | const Core::System& system, const BuildID& build_id) const; | 60 | const BuildID& build_id) const; |
| 54 | 61 | ||
| 55 | // Currently tracked RomFS patches: | 62 | // Currently tracked RomFS patches: |
| 56 | // - Game Updates | 63 | // - Game Updates |
| @@ -80,6 +87,8 @@ private: | |||
| 80 | const std::string& build_id) const; | 87 | const std::string& build_id) const; |
| 81 | 88 | ||
| 82 | u64 title_id; | 89 | u64 title_id; |
| 90 | const Service::FileSystem::FileSystemController& fs_controller; | ||
| 91 | const ContentProvider& content_provider; | ||
| 83 | }; | 92 | }; |
| 84 | 93 | ||
| 85 | } // namespace FileSys | 94 | } // namespace FileSys |
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index e967a254e..987199747 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -37,10 +37,12 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw) { | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { | 39 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { |
| 40 | if (!updatable) | 40 | if (!updatable) { |
| 41 | return MakeResult<VirtualFile>(file); | 41 | return MakeResult<VirtualFile>(file); |
| 42 | } | ||
| 42 | 43 | ||
| 43 | const PatchManager patch_manager(current_process_title_id); | 44 | const PatchManager patch_manager{current_process_title_id, filesystem_controller, |
| 45 | content_provider}; | ||
| 44 | return MakeResult<VirtualFile>( | 46 | return MakeResult<VirtualFile>( |
| 45 | patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw)); | 47 | patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw)); |
| 46 | } | 48 | } |
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 90641d23b..c05735ddd 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp | |||
| @@ -20,8 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | namespace FileSys { | 21 | namespace FileSys { |
| 22 | 22 | ||
| 23 | NSP::NSP(VirtualFile file_) | 23 | NSP::NSP(VirtualFile file_, std::size_t program_index) |
| 24 | : file(std::move(file_)), status{Loader::ResultStatus::Success}, | 24 | : file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success}, |
| 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { | 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { |
| 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { | 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { |
| 27 | status = pfs->GetStatus(); | 27 | status = pfs->GetStatus(); |
| @@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType | |||
| 146 | if (extracted) | 146 | if (extracted) |
| 147 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); | 147 | LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); |
| 148 | 148 | ||
| 149 | const auto title_id_iter = ncas.find(title_id); | 149 | const auto title_id_iter = ncas.find(title_id + program_index); |
| 150 | if (title_id_iter == ncas.end()) | 150 | if (title_id_iter == ncas.end()) |
| 151 | return nullptr; | 151 | return nullptr; |
| 152 | 152 | ||
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index c70a11b5b..54581a6f3 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h | |||
| @@ -27,7 +27,7 @@ enum class ContentRecordType : u8; | |||
| 27 | 27 | ||
| 28 | class NSP : public ReadOnlyVfsDirectory { | 28 | class NSP : public ReadOnlyVfsDirectory { |
| 29 | public: | 29 | public: |
| 30 | explicit NSP(VirtualFile file); | 30 | explicit NSP(VirtualFile file, std::size_t program_index = 0); |
| 31 | ~NSP() override; | 31 | ~NSP() override; |
| 32 | 32 | ||
| 33 | Loader::ResultStatus GetStatus() const; | 33 | Loader::ResultStatus GetStatus() const; |
| @@ -69,6 +69,8 @@ private: | |||
| 69 | 69 | ||
| 70 | VirtualFile file; | 70 | VirtualFile file; |
| 71 | 71 | ||
| 72 | const std::size_t program_index; | ||
| 73 | |||
| 72 | bool extracted = false; | 74 | bool extracted = false; |
| 73 | Loader::ResultStatus status; | 75 | Loader::ResultStatus status; |
| 74 | std::map<u64, Loader::ResultStatus> program_status; | 76 | std::map<u64, Loader::ResultStatus> program_status; |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 5582091f4..03bbedf8b 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -27,19 +27,19 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb | |||
| 27 | ->GetAppletResource() | 27 | ->GetAppletResource() |
| 28 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | 28 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); |
| 29 | 29 | ||
| 30 | auto& players = Settings::values.players; | 30 | auto& players = Settings::values.players.GetValue(); |
| 31 | 31 | ||
| 32 | const std::size_t min_supported_players = | 32 | const std::size_t min_supported_players = |
| 33 | parameters.enable_single_mode ? 1 : parameters.min_players; | 33 | parameters.enable_single_mode ? 1 : parameters.min_players; |
| 34 | 34 | ||
| 35 | // Disconnect Handheld first. | 35 | // Disconnect Handheld first. |
| 36 | npad.DisconnectNPadAtIndex(8); | 36 | npad.DisconnectNpadAtIndex(8); |
| 37 | 37 | ||
| 38 | // Deduce the best configuration based on the input parameters. | 38 | // Deduce the best configuration based on the input parameters. |
| 39 | for (std::size_t index = 0; index < players.size() - 2; ++index) { | 39 | for (std::size_t index = 0; index < players.size() - 2; ++index) { |
| 40 | // First, disconnect all controllers regardless of the value of keep_controllers_connected. | 40 | // First, disconnect all controllers regardless of the value of keep_controllers_connected. |
| 41 | // This makes it easy to connect the desired controllers. | 41 | // This makes it easy to connect the desired controllers. |
| 42 | npad.DisconnectNPadAtIndex(index); | 42 | npad.DisconnectNpadAtIndex(index); |
| 43 | 43 | ||
| 44 | // Only connect the minimum number of required players. | 44 | // Only connect the minimum number of required players. |
| 45 | if (index >= min_supported_players) { | 45 | if (index >= min_supported_players) { |
| @@ -66,7 +66,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb | |||
| 66 | npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); | 66 | npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); |
| 67 | } | 67 | } |
| 68 | } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && | 68 | } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && |
| 69 | !Settings::values.use_docked_mode) { | 69 | !Settings::values.use_docked_mode.GetValue()) { |
| 70 | // We should *never* reach here under any normal circumstances. | 70 | // We should *never* reach here under any normal circumstances. |
| 71 | npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), | 71 | npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), |
| 72 | index); | 72 | index); |
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 1acc82497..b9a270a55 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp | |||
| @@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { | |||
| 47 | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | 47 | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { |
| 48 | u32 width, height; | 48 | u32 width, height; |
| 49 | 49 | ||
| 50 | if (Settings::values.use_docked_mode) { | 50 | if (Settings::values.use_docked_mode.GetValue()) { |
| 51 | width = ScreenDocked::Width * res_scale; | 51 | width = ScreenDocked::Width * res_scale; |
| 52 | height = ScreenDocked::Height * res_scale; | 52 | height = ScreenDocked::Height * res_scale; |
| 53 | } else { | 53 | } else { |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 277b70e53..11c2e96ca 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h | |||
| @@ -30,10 +30,12 @@ public: | |||
| 30 | virtual StatusType GetStatus() const { | 30 | virtual StatusType GetStatus() const { |
| 31 | return {}; | 31 | return {}; |
| 32 | } | 32 | } |
| 33 | virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { | 33 | virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { |
| 34 | return {}; | 34 | return {}; |
| 35 | } | 35 | } |
| 36 | virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const { | 36 | virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low, |
| 37 | [[maybe_unused]] f32 amp_high, | ||
| 38 | [[maybe_unused]] f32 freq_high) const { | ||
| 37 | return {}; | 39 | return {}; |
| 38 | } | 40 | } |
| 39 | }; | 41 | }; |
| @@ -122,6 +124,13 @@ using ButtonDevice = InputDevice<bool>; | |||
| 122 | using AnalogDevice = InputDevice<std::tuple<float, float>>; | 124 | using AnalogDevice = InputDevice<std::tuple<float, float>>; |
| 123 | 125 | ||
| 124 | /** | 126 | /** |
| 127 | * A vibration device is an input device that returns an unsigned byte as status. | ||
| 128 | * It represents whether the vibration device supports vibration or not. | ||
| 129 | * If the status returns 1, it supports vibration. Otherwise, it does not support vibration. | ||
| 130 | */ | ||
| 131 | using VibrationDevice = InputDevice<u8>; | ||
| 132 | |||
| 133 | /** | ||
| 125 | * A motion status is an object that returns a tuple of accelerometer state vector, | 134 | * A motion status is an object that returns a tuple of accelerometer state vector, |
| 126 | * gyroscope state vector, rotation state vector and orientation state matrix. | 135 | * gyroscope state vector, rotation state vector and orientation state matrix. |
| 127 | * | 136 | * |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bafd1ced7..e3b770d66 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -681,7 +681,7 @@ static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { | |||
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 683 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 684 | static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) { | 684 | static void OutputDebugString(Core::System& system, VAddr address, u64 len) { |
| 685 | if (len == 0) { | 685 | if (len == 0) { |
| 686 | return; | 686 | return; |
| 687 | } | 687 | } |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index ded52ea0b..c2c11dbcb 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -742,8 +742,10 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx | |||
| 742 | bool is_locked = false; | 742 | bool is_locked = false; |
| 743 | 743 | ||
| 744 | if (res != Loader::ResultStatus::Success) { | 744 | if (res != Loader::ResultStatus::Success) { |
| 745 | FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; | 745 | const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(), |
| 746 | auto nacp_unique = pm.GetControlMetadata().first; | 746 | system.GetFileSystemController(), |
| 747 | system.GetContentProvider()}; | ||
| 748 | const auto nacp_unique = pm.GetControlMetadata().first; | ||
| 747 | 749 | ||
| 748 | if (nacp_unique != nullptr) { | 750 | if (nacp_unique != nullptr) { |
| 749 | is_locked = nacp_unique->GetUserAccountSwitchLock(); | 751 | is_locked = nacp_unique->GetUserAccountSwitchLock(); |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 2ce742e35..703a9b234 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -246,9 +246,8 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { | |||
| 246 | 246 | ||
| 247 | IDebugFunctions::~IDebugFunctions() = default; | 247 | IDebugFunctions::~IDebugFunctions() = default; |
| 248 | 248 | ||
| 249 | ISelfController::ISelfController(Core::System& system, | 249 | ISelfController::ISelfController(Core::System& system, NVFlinger::NVFlinger& nvflinger) |
| 250 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger) | 250 | : ServiceFramework("ISelfController"), system(system), nvflinger(nvflinger) { |
| 251 | : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) { | ||
| 252 | // clang-format off | 251 | // clang-format off |
| 253 | static const FunctionInfo functions[] = { | 252 | static const FunctionInfo functions[] = { |
| 254 | {0, &ISelfController::Exit, "Exit"}, | 253 | {0, &ISelfController::Exit, "Exit"}, |
| @@ -458,8 +457,8 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) | |||
| 458 | 457 | ||
| 459 | // TODO(Subv): Find out how AM determines the display to use, for now just | 458 | // TODO(Subv): Find out how AM determines the display to use, for now just |
| 460 | // create the layer in the Default display. | 459 | // create the layer in the Default display. |
| 461 | const auto display_id = nvflinger->OpenDisplay("Default"); | 460 | const auto display_id = nvflinger.OpenDisplay("Default"); |
| 462 | const auto layer_id = nvflinger->CreateLayer(*display_id); | 461 | const auto layer_id = nvflinger.CreateLayer(*display_id); |
| 463 | 462 | ||
| 464 | IPC::ResponseBuilder rb{ctx, 4}; | 463 | IPC::ResponseBuilder rb{ctx, 4}; |
| 465 | rb.Push(RESULT_SUCCESS); | 464 | rb.Push(RESULT_SUCCESS); |
| @@ -476,8 +475,8 @@ void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestConte | |||
| 476 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | 475 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse |
| 477 | // side effects. | 476 | // side effects. |
| 478 | // TODO: Support multiple layers | 477 | // TODO: Support multiple layers |
| 479 | const auto display_id = nvflinger->OpenDisplay("Default"); | 478 | const auto display_id = nvflinger.OpenDisplay("Default"); |
| 480 | const auto layer_id = nvflinger->CreateLayer(*display_id); | 479 | const auto layer_id = nvflinger.CreateLayer(*display_id); |
| 481 | 480 | ||
| 482 | IPC::ResponseBuilder rb{ctx, 4}; | 481 | IPC::ResponseBuilder rb{ctx, 4}; |
| 483 | rb.Push(RESULT_SUCCESS); | 482 | rb.Push(RESULT_SUCCESS); |
| @@ -751,7 +750,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& | |||
| 751 | IPC::ResponseBuilder rb{ctx, 4}; | 750 | IPC::ResponseBuilder rb{ctx, 4}; |
| 752 | rb.Push(RESULT_SUCCESS); | 751 | rb.Push(RESULT_SUCCESS); |
| 753 | 752 | ||
| 754 | if (Settings::values.use_docked_mode) { | 753 | if (Settings::values.use_docked_mode.GetValue()) { |
| 755 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 754 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 756 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); | 755 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 757 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 756 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
| @@ -824,7 +823,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) { | |||
| 824 | } | 823 | } |
| 825 | 824 | ||
| 826 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { | 825 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { |
| 827 | const bool use_docked_mode{Settings::values.use_docked_mode}; | 826 | const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()}; |
| 828 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | 827 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); |
| 829 | 828 | ||
| 830 | IPC::ResponseBuilder rb{ctx, 3}; | 829 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -1189,9 +1188,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1189 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, | 1188 | {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, |
| 1190 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, | 1189 | {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, |
| 1191 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, | 1190 | {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, |
| 1192 | {120, nullptr, "ExecuteProgram"}, | 1191 | {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, |
| 1193 | {121, nullptr, "ClearUserChannel"}, | 1192 | {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, |
| 1194 | {122, nullptr, "UnpopToUserChannel"}, | 1193 | {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, |
| 1195 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, | 1194 | {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, |
| 1196 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | 1195 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, |
| 1197 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | 1196 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, |
| @@ -1381,13 +1380,16 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { | |||
| 1381 | const auto res = [this] { | 1380 | const auto res = [this] { |
| 1382 | const auto title_id = system.CurrentProcess()->GetTitleID(); | 1381 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 1383 | 1382 | ||
| 1384 | FileSys::PatchManager pm{title_id}; | 1383 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1384 | system.GetContentProvider()}; | ||
| 1385 | auto res = pm.GetControlMetadata(); | 1385 | auto res = pm.GetControlMetadata(); |
| 1386 | if (res.first != nullptr) { | 1386 | if (res.first != nullptr) { |
| 1387 | return res; | 1387 | return res; |
| 1388 | } | 1388 | } |
| 1389 | 1389 | ||
| 1390 | FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; | 1390 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
| 1391 | system.GetFileSystemController(), | ||
| 1392 | system.GetContentProvider()}; | ||
| 1391 | return pm_update.GetControlMetadata(); | 1393 | return pm_update.GetControlMetadata(); |
| 1392 | }(); | 1394 | }(); |
| 1393 | 1395 | ||
| @@ -1415,13 +1417,16 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { | |||
| 1415 | const auto res = [this] { | 1417 | const auto res = [this] { |
| 1416 | const auto title_id = system.CurrentProcess()->GetTitleID(); | 1418 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 1417 | 1419 | ||
| 1418 | FileSys::PatchManager pm{title_id}; | 1420 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1421 | system.GetContentProvider()}; | ||
| 1419 | auto res = pm.GetControlMetadata(); | 1422 | auto res = pm.GetControlMetadata(); |
| 1420 | if (res.first != nullptr) { | 1423 | if (res.first != nullptr) { |
| 1421 | return res; | 1424 | return res; |
| 1422 | } | 1425 | } |
| 1423 | 1426 | ||
| 1424 | FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; | 1427 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
| 1428 | system.GetFileSystemController(), | ||
| 1429 | system.GetContentProvider()}; | ||
| 1425 | return pm_update.GetControlMetadata(); | 1430 | return pm_update.GetControlMetadata(); |
| 1426 | }(); | 1431 | }(); |
| 1427 | 1432 | ||
| @@ -1556,6 +1561,34 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque | |||
| 1556 | rb.Push<u32>(0); | 1561 | rb.Push<u32>(0); |
| 1557 | } | 1562 | } |
| 1558 | 1563 | ||
| 1564 | void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) { | ||
| 1565 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1566 | |||
| 1567 | IPC::RequestParser rp{ctx}; | ||
| 1568 | [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); | ||
| 1569 | [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); | ||
| 1570 | const auto program_index = rp.Pop<u64>(); | ||
| 1571 | |||
| 1572 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1573 | rb.Push(RESULT_SUCCESS); | ||
| 1574 | |||
| 1575 | system.ExecuteProgram(program_index); | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | void IApplicationFunctions::ClearUserChannel(Kernel::HLERequestContext& ctx) { | ||
| 1579 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1580 | |||
| 1581 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1582 | rb.Push(RESULT_SUCCESS); | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | void IApplicationFunctions::UnpopToUserChannel(Kernel::HLERequestContext& ctx) { | ||
| 1586 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 1587 | |||
| 1588 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1589 | rb.Push(RESULT_SUCCESS); | ||
| 1590 | } | ||
| 1591 | |||
| 1559 | void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) { | 1592 | void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) { |
| 1560 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 1593 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 1561 | 1594 | ||
| @@ -1580,8 +1613,8 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe | |||
| 1580 | rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); | 1613 | rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); |
| 1581 | } | 1614 | } |
| 1582 | 1615 | ||
| 1583 | void InstallInterfaces(SM::ServiceManager& service_manager, | 1616 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, |
| 1584 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) { | 1617 | Core::System& system) { |
| 1585 | auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); | 1618 | auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); |
| 1586 | // Needed on game boot | 1619 | // Needed on game boot |
| 1587 | message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | 1620 | message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index bcc06affe..af97c303a 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -121,8 +121,7 @@ public: | |||
| 121 | 121 | ||
| 122 | class ISelfController final : public ServiceFramework<ISelfController> { | 122 | class ISelfController final : public ServiceFramework<ISelfController> { |
| 123 | public: | 123 | public: |
| 124 | explicit ISelfController(Core::System& system_, | 124 | explicit ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_); |
| 125 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger_); | ||
| 126 | ~ISelfController() override; | 125 | ~ISelfController() override; |
| 127 | 126 | ||
| 128 | private: | 127 | private: |
| @@ -156,7 +155,7 @@ private: | |||
| 156 | }; | 155 | }; |
| 157 | 156 | ||
| 158 | Core::System& system; | 157 | Core::System& system; |
| 159 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 158 | NVFlinger::NVFlinger& nvflinger; |
| 160 | Kernel::EventPair launchable_event; | 159 | Kernel::EventPair launchable_event; |
| 161 | Kernel::EventPair accumulated_suspended_tick_changed_event; | 160 | Kernel::EventPair accumulated_suspended_tick_changed_event; |
| 162 | 161 | ||
| @@ -288,6 +287,9 @@ private: | |||
| 288 | void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx); | 287 | void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx); |
| 289 | void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx); | 288 | void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx); |
| 290 | void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx); | 289 | void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx); |
| 290 | void ExecuteProgram(Kernel::HLERequestContext& ctx); | ||
| 291 | void ClearUserChannel(Kernel::HLERequestContext& ctx); | ||
| 292 | void UnpopToUserChannel(Kernel::HLERequestContext& ctx); | ||
| 291 | void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx); | 293 | void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx); |
| 292 | void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); | 294 | void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); |
| 293 | void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); | 295 | void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); |
| @@ -332,7 +334,7 @@ public: | |||
| 332 | }; | 334 | }; |
| 333 | 335 | ||
| 334 | /// Registers all AM services with the specified service manager. | 336 | /// Registers all AM services with the specified service manager. |
| 335 | void InstallInterfaces(SM::ServiceManager& service_manager, | 337 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, |
| 336 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system); | 338 | Core::System& system); |
| 337 | 339 | ||
| 338 | } // namespace Service::AM | 340 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index be23ca747..7de506b70 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp | |||
| @@ -13,10 +13,10 @@ namespace Service::AM { | |||
| 13 | 13 | ||
| 14 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | 14 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { |
| 15 | public: | 15 | public: |
| 16 | explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 16 | explicit ILibraryAppletProxy(NVFlinger::NVFlinger& nvflinger, |
| 17 | std::shared_ptr<AppletMessageQueue> msg_queue, | 17 | std::shared_ptr<AppletMessageQueue> msg_queue, |
| 18 | Core::System& system) | 18 | Core::System& system) |
| 19 | : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), | 19 | : ServiceFramework("ILibraryAppletProxy"), nvflinger(nvflinger), |
| 20 | msg_queue(std::move(msg_queue)), system(system) { | 20 | msg_queue(std::move(msg_queue)), system(system) { |
| 21 | // clang-format off | 21 | // clang-format off |
| 22 | static const FunctionInfo functions[] = { | 22 | static const FunctionInfo functions[] = { |
| @@ -109,16 +109,16 @@ private: | |||
| 109 | rb.PushIpcInterface<IApplicationFunctions>(system); | 109 | rb.PushIpcInterface<IApplicationFunctions>(system); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 112 | NVFlinger::NVFlinger& nvflinger; |
| 113 | std::shared_ptr<AppletMessageQueue> msg_queue; | 113 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 114 | Core::System& system; | 114 | Core::System& system; |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | 117 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { |
| 118 | public: | 118 | public: |
| 119 | explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 119 | explicit ISystemAppletProxy(NVFlinger::NVFlinger& nvflinger, |
| 120 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) | 120 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 121 | : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), | 121 | : ServiceFramework("ISystemAppletProxy"), nvflinger(nvflinger), |
| 122 | msg_queue(std::move(msg_queue)), system(system) { | 122 | msg_queue(std::move(msg_queue)), system(system) { |
| 123 | // clang-format off | 123 | // clang-format off |
| 124 | static const FunctionInfo functions[] = { | 124 | static const FunctionInfo functions[] = { |
| @@ -220,7 +220,8 @@ private: | |||
| 220 | rb.Push(RESULT_SUCCESS); | 220 | rb.Push(RESULT_SUCCESS); |
| 221 | rb.PushIpcInterface<IApplicationCreator>(); | 221 | rb.PushIpcInterface<IApplicationCreator>(); |
| 222 | } | 222 | } |
| 223 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 223 | |
| 224 | NVFlinger::NVFlinger& nvflinger; | ||
| 224 | std::shared_ptr<AppletMessageQueue> msg_queue; | 225 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 225 | Core::System& system; | 226 | Core::System& system; |
| 226 | }; | 227 | }; |
| @@ -249,10 +250,10 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { | |||
| 249 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); | 250 | rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); |
| 250 | } | 251 | } |
| 251 | 252 | ||
| 252 | AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 253 | AppletAE::AppletAE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue, |
| 253 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) | 254 | Core::System& system) |
| 254 | : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), | 255 | : ServiceFramework("appletAE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)), |
| 255 | msg_queue(std::move(msg_queue)), system(system) { | 256 | system(system) { |
| 256 | // clang-format off | 257 | // clang-format off |
| 257 | static const FunctionInfo functions[] = { | 258 | static const FunctionInfo functions[] = { |
| 258 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, | 259 | {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, |
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 2e3e45915..761844a1f 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h | |||
| @@ -23,7 +23,7 @@ class AppletMessageQueue; | |||
| 23 | 23 | ||
| 24 | class AppletAE final : public ServiceFramework<AppletAE> { | 24 | class AppletAE final : public ServiceFramework<AppletAE> { |
| 25 | public: | 25 | public: |
| 26 | explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 26 | explicit AppletAE(NVFlinger::NVFlinger& nvflinger, |
| 27 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); | 27 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); |
| 28 | ~AppletAE() override; | 28 | ~AppletAE() override; |
| 29 | 29 | ||
| @@ -34,7 +34,7 @@ private: | |||
| 34 | void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); | 34 | void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); |
| 35 | void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); | 35 | void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); |
| 36 | 36 | ||
| 37 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 37 | NVFlinger::NVFlinger& nvflinger; |
| 38 | std::shared_ptr<AppletMessageQueue> msg_queue; | 38 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 39 | Core::System& system; | 39 | Core::System& system; |
| 40 | }; | 40 | }; |
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index a2ffaa440..7bed86ec4 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -12,9 +12,9 @@ namespace Service::AM { | |||
| 12 | 12 | ||
| 13 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | 13 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { |
| 14 | public: | 14 | public: |
| 15 | explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 15 | explicit IApplicationProxy(NVFlinger::NVFlinger& nvflinger, |
| 16 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) | 16 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) |
| 17 | : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), | 17 | : ServiceFramework("IApplicationProxy"), nvflinger(nvflinger), |
| 18 | msg_queue(std::move(msg_queue)), system(system) { | 18 | msg_queue(std::move(msg_queue)), system(system) { |
| 19 | // clang-format off | 19 | // clang-format off |
| 20 | static const FunctionInfo functions[] = { | 20 | static const FunctionInfo functions[] = { |
| @@ -98,7 +98,7 @@ private: | |||
| 98 | rb.PushIpcInterface<IApplicationFunctions>(system); | 98 | rb.PushIpcInterface<IApplicationFunctions>(system); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 101 | NVFlinger::NVFlinger& nvflinger; |
| 102 | std::shared_ptr<AppletMessageQueue> msg_queue; | 102 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 103 | Core::System& system; | 103 | Core::System& system; |
| 104 | }; | 104 | }; |
| @@ -111,10 +111,10 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { | |||
| 111 | rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system); | 111 | rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 114 | AppletOE::AppletOE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue, |
| 115 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) | 115 | Core::System& system) |
| 116 | : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), | 116 | : ServiceFramework("appletOE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)), |
| 117 | msg_queue(std::move(msg_queue)), system(system) { | 117 | system(system) { |
| 118 | static const FunctionInfo functions[] = { | 118 | static const FunctionInfo functions[] = { |
| 119 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, | 119 | {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, |
| 120 | }; | 120 | }; |
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 758da792d..88906d354 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h | |||
| @@ -23,7 +23,7 @@ class AppletMessageQueue; | |||
| 23 | 23 | ||
| 24 | class AppletOE final : public ServiceFramework<AppletOE> { | 24 | class AppletOE final : public ServiceFramework<AppletOE> { |
| 25 | public: | 25 | public: |
| 26 | explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, | 26 | explicit AppletOE(NVFlinger::NVFlinger& nvflinger, |
| 27 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); | 27 | std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); |
| 28 | ~AppletOE() override; | 28 | ~AppletOE() override; |
| 29 | 29 | ||
| @@ -32,7 +32,7 @@ public: | |||
| 32 | private: | 32 | private: |
| 33 | void OpenApplicationProxy(Kernel::HLERequestContext& ctx); | 33 | void OpenApplicationProxy(Kernel::HLERequestContext& ctx); |
| 34 | 34 | ||
| 35 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 35 | NVFlinger::NVFlinger& nvflinger; |
| 36 | std::shared_ptr<AppletMessageQueue> msg_queue; | 36 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 37 | Core::System& system; | 37 | Core::System& system; |
| 38 | }; | 38 | }; |
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index a0152b4ea..3ca63f020 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp | |||
| @@ -25,7 +25,7 @@ namespace Service::AM::Applets { | |||
| 25 | static Core::Frontend::ControllerParameters ConvertToFrontendParameters( | 25 | static Core::Frontend::ControllerParameters ConvertToFrontendParameters( |
| 26 | ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, | 26 | ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, |
| 27 | std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { | 27 | std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { |
| 28 | HID::Controller_NPad::NPadType npad_style_set; | 28 | HID::Controller_NPad::NpadStyleSet npad_style_set; |
| 29 | npad_style_set.raw = private_arg.style_set; | 29 | npad_style_set.raw = private_arg.style_set; |
| 30 | 30 | ||
| 31 | return { | 31 | return { |
| @@ -222,7 +222,7 @@ void Controller::Execute() { | |||
| 222 | void Controller::ConfigurationComplete() { | 222 | void Controller::ConfigurationComplete() { |
| 223 | ControllerSupportResultInfo result_info{}; | 223 | ControllerSupportResultInfo result_info{}; |
| 224 | 224 | ||
| 225 | const auto& players = Settings::values.players; | 225 | const auto& players = Settings::values.players.GetValue(); |
| 226 | 226 | ||
| 227 | // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. | 227 | // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. |
| 228 | // Otherwise, only count connected players from P1-P8. | 228 | // Otherwise, only count connected players from P1-P8. |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index e58b2c518..173b36da4 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -164,7 +164,8 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { | |||
| 164 | rb.Push(RESULT_SUCCESS); | 164 | rb.Push(RESULT_SUCCESS); |
| 165 | 165 | ||
| 166 | const auto title_id = system.CurrentProcess()->GetTitleID(); | 166 | const auto title_id = system.CurrentProcess()->GetTitleID(); |
| 167 | FileSys::PatchManager pm{title_id}; | 167 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 168 | system.GetContentProvider()}; | ||
| 168 | 169 | ||
| 169 | const auto res = pm.GetControlMetadata(); | 170 | const auto res = pm.GetControlMetadata(); |
| 170 | if (res.first == nullptr) { | 171 | if (res.first == nullptr) { |
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp index 25a886238..ce993bad3 100644 --- a/src/core/hle/service/apm/controller.cpp +++ b/src/core/hle/service/apm/controller.cpp | |||
| @@ -69,7 +69,8 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | PerformanceMode Controller::GetCurrentPerformanceMode() const { | 71 | PerformanceMode Controller::GetCurrentPerformanceMode() const { |
| 72 | return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld; | 72 | return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Docked |
| 73 | : PerformanceMode::Handheld; | ||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) { | 76 | PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) { |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3cdef4888..2e53cae5b 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -455,7 +455,9 @@ FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataTy | |||
| 455 | const auto res = system.GetAppLoader().ReadControlData(nacp); | 455 | const auto res = system.GetAppLoader().ReadControlData(nacp); |
| 456 | 456 | ||
| 457 | if (res != Loader::ResultStatus::Success) { | 457 | if (res != Loader::ResultStatus::Success) { |
| 458 | FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; | 458 | const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(), |
| 459 | system.GetFileSystemController(), | ||
| 460 | system.GetContentProvider()}; | ||
| 459 | const auto metadata = pm.GetControlMetadata(); | 461 | const auto metadata = pm.GetControlMetadata(); |
| 460 | const auto& nacp_unique = metadata.first; | 462 | const auto& nacp_unique = metadata.first; |
| 461 | 463 | ||
| @@ -728,7 +730,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove | |||
| 728 | void InstallInterfaces(Core::System& system) { | 730 | void InstallInterfaces(Core::System& system) { |
| 729 | std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager()); | 731 | std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager()); |
| 730 | std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager()); | 732 | std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager()); |
| 731 | std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter()) | 733 | std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetContentProvider(), |
| 734 | system.GetReporter()) | ||
| 732 | ->InstallAsService(system.ServiceManager()); | 735 | ->InstallAsService(system.ServiceManager()); |
| 733 | } | 736 | } |
| 734 | 737 | ||
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 649128be4..031c6dbf6 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -650,8 +650,10 @@ private: | |||
| 650 | u64 next_entry_index = 0; | 650 | u64 next_entry_index = 0; |
| 651 | }; | 651 | }; |
| 652 | 652 | ||
| 653 | FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) | 653 | FSP_SRV::FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_, |
| 654 | : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) { | 654 | const Core::Reporter& reporter_) |
| 655 | : ServiceFramework("fsp-srv"), fsc(fsc_), content_provider{content_provider_}, | ||
| 656 | reporter(reporter_) { | ||
| 655 | // clang-format off | 657 | // clang-format off |
| 656 | static const FunctionInfo functions[] = { | 658 | static const FunctionInfo functions[] = { |
| 657 | {0, nullptr, "OpenFileSystem"}, | 659 | {0, nullptr, "OpenFileSystem"}, |
| @@ -968,7 +970,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { | |||
| 968 | return; | 970 | return; |
| 969 | } | 971 | } |
| 970 | 972 | ||
| 971 | FileSys::PatchManager pm{title_id}; | 973 | const FileSys::PatchManager pm{title_id, fsc, content_provider}; |
| 972 | 974 | ||
| 973 | auto storage = std::make_shared<IStorage>( | 975 | auto storage = std::make_shared<IStorage>( |
| 974 | pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); | 976 | pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); |
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 4964e874e..6c7239e6a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h | |||
| @@ -12,8 +12,9 @@ class Reporter; | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| 15 | class ContentProvider; | ||
| 15 | class FileSystemBackend; | 16 | class FileSystemBackend; |
| 16 | } | 17 | } // namespace FileSys |
| 17 | 18 | ||
| 18 | namespace Service::FileSystem { | 19 | namespace Service::FileSystem { |
| 19 | 20 | ||
| @@ -32,7 +33,8 @@ enum class LogMode : u32 { | |||
| 32 | 33 | ||
| 33 | class FSP_SRV final : public ServiceFramework<FSP_SRV> { | 34 | class FSP_SRV final : public ServiceFramework<FSP_SRV> { |
| 34 | public: | 35 | public: |
| 35 | explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter); | 36 | explicit FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_, |
| 37 | const Core::Reporter& reporter_); | ||
| 36 | ~FSP_SRV() override; | 38 | ~FSP_SRV() override; |
| 37 | 39 | ||
| 38 | private: | 40 | private: |
| @@ -55,6 +57,7 @@ private: | |||
| 55 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); | 57 | void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); |
| 56 | 58 | ||
| 57 | FileSystemController& fsc; | 59 | FileSystemController& fsc; |
| 60 | const FileSys::ContentProvider& content_provider; | ||
| 58 | 61 | ||
| 59 | FileSys::VirtualFile romfs; | 62 | FileSys::VirtualFile romfs; |
| 60 | u64 current_process_id = 0; | 63 | u64 current_process_id = 0; |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e311bc18c..e2539ded8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -117,7 +117,10 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 120 | Controller_NPad::~Controller_NPad() = default; | 120 | |
| 121 | Controller_NPad::~Controller_NPad() { | ||
| 122 | OnRelease(); | ||
| 123 | } | ||
| 121 | 124 | ||
| 122 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | 125 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 123 | const auto controller_type = connected_controllers[controller_idx].type; | 126 | const auto controller_type = connected_controllers[controller_idx].type; |
| @@ -139,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 139 | controller.properties.is_vertical.Assign(1); | 142 | controller.properties.is_vertical.Assign(1); |
| 140 | controller.properties.use_plus.Assign(1); | 143 | controller.properties.use_plus.Assign(1); |
| 141 | controller.properties.use_minus.Assign(1); | 144 | controller.properties.use_minus.Assign(1); |
| 142 | controller.pad_assignment = NPadAssignments::Single; | 145 | controller.pad_assignment = NpadAssignments::Single; |
| 143 | break; | 146 | break; |
| 144 | case NPadControllerType::Handheld: | 147 | case NPadControllerType::Handheld: |
| 145 | controller.joy_styles.handheld.Assign(1); | 148 | controller.joy_styles.handheld.Assign(1); |
| @@ -147,7 +150,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 147 | controller.properties.is_vertical.Assign(1); | 150 | controller.properties.is_vertical.Assign(1); |
| 148 | controller.properties.use_plus.Assign(1); | 151 | controller.properties.use_plus.Assign(1); |
| 149 | controller.properties.use_minus.Assign(1); | 152 | controller.properties.use_minus.Assign(1); |
| 150 | controller.pad_assignment = NPadAssignments::Dual; | 153 | controller.pad_assignment = NpadAssignments::Dual; |
| 151 | break; | 154 | break; |
| 152 | case NPadControllerType::JoyDual: | 155 | case NPadControllerType::JoyDual: |
| 153 | controller.joy_styles.joycon_dual.Assign(1); | 156 | controller.joy_styles.joycon_dual.Assign(1); |
| @@ -156,26 +159,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 156 | controller.properties.is_vertical.Assign(1); | 159 | controller.properties.is_vertical.Assign(1); |
| 157 | controller.properties.use_plus.Assign(1); | 160 | controller.properties.use_plus.Assign(1); |
| 158 | controller.properties.use_minus.Assign(1); | 161 | controller.properties.use_minus.Assign(1); |
| 159 | controller.pad_assignment = NPadAssignments::Dual; | 162 | controller.pad_assignment = NpadAssignments::Dual; |
| 160 | break; | 163 | break; |
| 161 | case NPadControllerType::JoyLeft: | 164 | case NPadControllerType::JoyLeft: |
| 162 | controller.joy_styles.joycon_left.Assign(1); | 165 | controller.joy_styles.joycon_left.Assign(1); |
| 163 | controller.device_type.joycon_left.Assign(1); | 166 | controller.device_type.joycon_left.Assign(1); |
| 164 | controller.properties.is_horizontal.Assign(1); | 167 | controller.properties.is_horizontal.Assign(1); |
| 165 | controller.properties.use_minus.Assign(1); | 168 | controller.properties.use_minus.Assign(1); |
| 166 | controller.pad_assignment = NPadAssignments::Single; | 169 | controller.pad_assignment = NpadAssignments::Single; |
| 167 | break; | 170 | break; |
| 168 | case NPadControllerType::JoyRight: | 171 | case NPadControllerType::JoyRight: |
| 169 | controller.joy_styles.joycon_right.Assign(1); | 172 | controller.joy_styles.joycon_right.Assign(1); |
| 170 | controller.device_type.joycon_right.Assign(1); | 173 | controller.device_type.joycon_right.Assign(1); |
| 171 | controller.properties.is_horizontal.Assign(1); | 174 | controller.properties.is_horizontal.Assign(1); |
| 172 | controller.properties.use_plus.Assign(1); | 175 | controller.properties.use_plus.Assign(1); |
| 173 | controller.pad_assignment = NPadAssignments::Single; | 176 | controller.pad_assignment = NpadAssignments::Single; |
| 174 | break; | 177 | break; |
| 175 | case NPadControllerType::Pokeball: | 178 | case NPadControllerType::Pokeball: |
| 176 | controller.joy_styles.pokeball.Assign(1); | 179 | controller.joy_styles.pokeball.Assign(1); |
| 177 | controller.device_type.pokeball.Assign(1); | 180 | controller.device_type.pokeball.Assign(1); |
| 178 | controller.pad_assignment = NPadAssignments::Single; | 181 | controller.pad_assignment = NpadAssignments::Single; |
| 179 | break; | 182 | break; |
| 180 | } | 183 | } |
| 181 | 184 | ||
| @@ -184,11 +187,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 184 | controller.single_color.button_color = 0; | 187 | controller.single_color.button_color = 0; |
| 185 | 188 | ||
| 186 | controller.dual_color_error = ColorReadError::ReadOk; | 189 | controller.dual_color_error = ColorReadError::ReadOk; |
| 187 | controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left; | 190 | controller.left_color.body_color = |
| 188 | controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left; | 191 | Settings::values.players.GetValue()[controller_idx].body_color_left; |
| 189 | controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right; | 192 | controller.left_color.button_color = |
| 193 | Settings::values.players.GetValue()[controller_idx].button_color_left; | ||
| 194 | controller.right_color.body_color = | ||
| 195 | Settings::values.players.GetValue()[controller_idx].body_color_right; | ||
| 190 | controller.right_color.button_color = | 196 | controller.right_color.button_color = |
| 191 | Settings::values.players[controller_idx].button_color_right; | 197 | Settings::values.players.GetValue()[controller_idx].button_color_right; |
| 192 | 198 | ||
| 193 | controller.battery_level[0] = BATTERY_FULL; | 199 | controller.battery_level[0] = BATTERY_FULL; |
| 194 | controller.battery_level[1] = BATTERY_FULL; | 200 | controller.battery_level[1] = BATTERY_FULL; |
| @@ -199,7 +205,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 199 | 205 | ||
| 200 | void Controller_NPad::OnInit() { | 206 | void Controller_NPad::OnInit() { |
| 201 | auto& kernel = system.Kernel(); | 207 | auto& kernel = system.Kernel(); |
| 202 | for (std::size_t i = 0; i < styleset_changed_events.size(); i++) { | 208 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { |
| 203 | styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( | 209 | styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( |
| 204 | kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); | 210 | kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); |
| 205 | } | 211 | } |
| @@ -208,6 +214,8 @@ void Controller_NPad::OnInit() { | |||
| 208 | return; | 214 | return; |
| 209 | } | 215 | } |
| 210 | 216 | ||
| 217 | OnLoadInputDevices(); | ||
| 218 | |||
| 211 | if (style.raw == 0) { | 219 | if (style.raw == 0) { |
| 212 | // We want to support all controllers | 220 | // We want to support all controllers |
| 213 | style.handheld.Assign(1); | 221 | style.handheld.Assign(1); |
| @@ -218,12 +226,27 @@ void Controller_NPad::OnInit() { | |||
| 218 | style.pokeball.Assign(1); | 226 | style.pokeball.Assign(1); |
| 219 | } | 227 | } |
| 220 | 228 | ||
| 221 | std::transform(Settings::values.players.begin(), Settings::values.players.end(), | 229 | std::transform(Settings::values.players.GetValue().begin(), |
| 222 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { | 230 | Settings::values.players.GetValue().end(), connected_controllers.begin(), |
| 231 | [](const Settings::PlayerInput& player) { | ||
| 223 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), | 232 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), |
| 224 | player.connected}; | 233 | player.connected}; |
| 225 | }); | 234 | }); |
| 226 | 235 | ||
| 236 | // Connect the Player 1 or Handheld controller if none are connected. | ||
| 237 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 238 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 239 | const auto controller = | ||
| 240 | MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); | ||
| 241 | if (controller == NPadControllerType::Handheld) { | ||
| 242 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; | ||
| 243 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 244 | } else { | ||
| 245 | Settings::values.players.GetValue()[0].connected = true; | ||
| 246 | connected_controllers[0] = {controller, true}; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 227 | // Account for handheld | 250 | // Account for handheld |
| 228 | if (connected_controllers[HANDHELD_INDEX].is_connected) { | 251 | if (connected_controllers[HANDHELD_INDEX].is_connected) { |
| 229 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; | 252 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; |
| @@ -242,7 +265,7 @@ void Controller_NPad::OnInit() { | |||
| 242 | } | 265 | } |
| 243 | 266 | ||
| 244 | void Controller_NPad::OnLoadInputDevices() { | 267 | void Controller_NPad::OnLoadInputDevices() { |
| 245 | const auto& players = Settings::values.players; | 268 | const auto& players = Settings::values.players.GetValue(); |
| 246 | for (std::size_t i = 0; i < players.size(); ++i) { | 269 | for (std::size_t i = 0; i < players.size(); ++i) { |
| 247 | std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | 270 | std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, |
| 248 | players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, | 271 | players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, |
| @@ -250,13 +273,26 @@ void Controller_NPad::OnLoadInputDevices() { | |||
| 250 | std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, | 273 | std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, |
| 251 | players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, | 274 | players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, |
| 252 | sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); | 275 | sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); |
| 276 | std::transform(players[i].vibrations.begin() + | ||
| 277 | Settings::NativeVibration::VIBRATION_HID_BEGIN, | ||
| 278 | players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, | ||
| 279 | vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>); | ||
| 253 | std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, | 280 | std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, |
| 254 | players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, | 281 | players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, |
| 255 | motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); | 282 | motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); |
| 283 | for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { | ||
| 284 | InitializeVibrationDeviceAtIndex(i, device_idx); | ||
| 285 | } | ||
| 256 | } | 286 | } |
| 257 | } | 287 | } |
| 258 | 288 | ||
| 259 | void Controller_NPad::OnRelease() {} | 289 | void Controller_NPad::OnRelease() { |
| 290 | for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { | ||
| 291 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { | ||
| 292 | VibrateControllerAtIndex(npad_idx, device_idx, {}); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 260 | 296 | ||
| 261 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | 297 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { |
| 262 | const auto controller_idx = NPadIdToIndex(npad_id); | 298 | const auto controller_idx = NPadIdToIndex(npad_id); |
| @@ -339,7 +375,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 339 | if (!IsControllerActivated()) { | 375 | if (!IsControllerActivated()) { |
| 340 | return; | 376 | return; |
| 341 | } | 377 | } |
| 342 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 378 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { |
| 343 | auto& npad = shared_memory_entries[i]; | 379 | auto& npad = shared_memory_entries[i]; |
| 344 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, | 380 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, |
| 345 | &npad.handheld_states, | 381 | &npad.handheld_states, |
| @@ -481,7 +517,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 481 | if (!IsControllerActivated()) { | 517 | if (!IsControllerActivated()) { |
| 482 | return; | 518 | return; |
| 483 | } | 519 | } |
| 484 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 520 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { |
| 485 | auto& npad = shared_memory_entries[i]; | 521 | auto& npad = shared_memory_entries[i]; |
| 486 | 522 | ||
| 487 | const auto& controller_type = connected_controllers[i].type; | 523 | const auto& controller_type = connected_controllers[i].type; |
| @@ -515,7 +551,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 515 | // Try to read sixaxis sensor states | 551 | // Try to read sixaxis sensor states |
| 516 | std::array<MotionDevice, 2> motion_devices; | 552 | std::array<MotionDevice, 2> motion_devices; |
| 517 | 553 | ||
| 518 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled) { | 554 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { |
| 519 | sixaxis_at_rest = true; | 555 | sixaxis_at_rest = true; |
| 520 | for (std::size_t e = 0; e < motion_devices.size(); ++e) { | 556 | for (std::size_t e = 0; e < motion_devices.size(); ++e) { |
| 521 | const auto& device = motions[i][e]; | 557 | const auto& device = motions[i][e]; |
| @@ -601,15 +637,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 601 | shared_memory_entries.size() * sizeof(NPadEntry)); | 637 | shared_memory_entries.size() * sizeof(NPadEntry)); |
| 602 | } | 638 | } |
| 603 | 639 | ||
| 604 | void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { | 640 | void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { |
| 605 | style.raw = style_set.raw; | 641 | style.raw = style_set.raw; |
| 606 | } | 642 | } |
| 607 | 643 | ||
| 608 | Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { | 644 | Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { |
| 609 | return style; | 645 | return style; |
| 610 | } | 646 | } |
| 611 | 647 | ||
| 612 | void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | 648 | void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { |
| 613 | ASSERT(length > 0 && (length % sizeof(u32)) == 0); | 649 | ASSERT(length > 0 && (length % sizeof(u32)) == 0); |
| 614 | supported_npad_id_types.clear(); | 650 | supported_npad_id_types.clear(); |
| 615 | supported_npad_id_types.resize(length / sizeof(u32)); | 651 | supported_npad_id_types.resize(length / sizeof(u32)); |
| @@ -621,7 +657,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) | |||
| 621 | std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); | 657 | std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); |
| 622 | } | 658 | } |
| 623 | 659 | ||
| 624 | std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { | 660 | std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { |
| 625 | return supported_npad_id_types.size(); | 661 | return supported_npad_id_types.size(); |
| 626 | } | 662 | } |
| 627 | 663 | ||
| @@ -641,7 +677,7 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi | |||
| 641 | return handheld_activation_mode; | 677 | return handheld_activation_mode; |
| 642 | } | 678 | } |
| 643 | 679 | ||
| 644 | void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { | 680 | void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { |
| 645 | const std::size_t npad_index = NPadIdToIndex(npad_id); | 681 | const std::size_t npad_index = NPadIdToIndex(npad_id); |
| 646 | ASSERT(npad_index < shared_memory_entries.size()); | 682 | ASSERT(npad_index < shared_memory_entries.size()); |
| 647 | if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { | 683 | if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { |
| @@ -649,35 +685,140 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) | |||
| 649 | } | 685 | } |
| 650 | } | 686 | } |
| 651 | 687 | ||
| 652 | void Controller_NPad::VibrateController(const std::vector<u32>& controllers, | 688 | bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 653 | const std::vector<Vibration>& vibrations) { | 689 | const VibrationValue& vibration_value) { |
| 654 | LOG_TRACE(Service_HID, "called"); | 690 | if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { |
| 655 | 691 | return false; | |
| 656 | if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { | ||
| 657 | return; | ||
| 658 | } | 692 | } |
| 659 | bool success = true; | 693 | |
| 660 | for (std::size_t i = 0; i < controllers.size(); ++i) { | 694 | const auto& player = Settings::values.players.GetValue()[npad_index]; |
| 661 | if (!connected_controllers[i].is_connected) { | 695 | |
| 662 | continue; | 696 | if (!player.vibration_enabled) { |
| 697 | if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || | ||
| 698 | latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { | ||
| 699 | // Send an empty vibration to stop any vibrations. | ||
| 700 | vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); | ||
| 701 | // Then reset the vibration value to its default value. | ||
| 702 | latest_vibration_values[npad_index][device_index] = {}; | ||
| 663 | } | 703 | } |
| 664 | using namespace Settings::NativeButton; | 704 | |
| 665 | const auto& button_state = buttons[i]; | 705 | return false; |
| 666 | if (button_state[A - BUTTON_HID_BEGIN]) { | 706 | } |
| 667 | if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( | 707 | |
| 668 | vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, | 708 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { |
| 669 | vibrations[0].freq_low)) { | 709 | using std::chrono::duration_cast; |
| 670 | success = false; | 710 | using std::chrono::milliseconds; |
| 671 | } | 711 | using std::chrono::steady_clock; |
| 712 | |||
| 713 | const auto now = steady_clock::now(); | ||
| 714 | |||
| 715 | // Filter out non-zero vibrations that are within 10ms of each other. | ||
| 716 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && | ||
| 717 | duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < | ||
| 718 | milliseconds(10)) { | ||
| 719 | return false; | ||
| 672 | } | 720 | } |
| 721 | |||
| 722 | last_vibration_timepoints[npad_index][device_index] = now; | ||
| 723 | } | ||
| 724 | |||
| 725 | auto& vibration = vibrations[npad_index][device_index]; | ||
| 726 | const auto player_vibration_strength = static_cast<f32>(player.vibration_strength); | ||
| 727 | const auto amp_low = | ||
| 728 | std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); | ||
| 729 | const auto amp_high = | ||
| 730 | std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); | ||
| 731 | return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, | ||
| 732 | vibration_value.freq_high); | ||
| 733 | } | ||
| 734 | |||
| 735 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 736 | const VibrationValue& vibration_value) { | ||
| 737 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 738 | return; | ||
| 739 | } | ||
| 740 | |||
| 741 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 742 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 743 | |||
| 744 | if (!vibration_devices_mounted[npad_index][device_index] || | ||
| 745 | !connected_controllers[npad_index].is_connected) { | ||
| 746 | return; | ||
| 673 | } | 747 | } |
| 674 | if (success) { | 748 | |
| 675 | last_processed_vibration = vibrations.back(); | 749 | if (vibration_device_handle.device_index == DeviceIndex::None) { |
| 750 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | ||
| 751 | return; | ||
| 752 | } | ||
| 753 | |||
| 754 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 755 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && | ||
| 756 | (vibration_device_handle.npad_type == NpadType::JoyconRight || | ||
| 757 | vibration_device_handle.device_index == DeviceIndex::Right)) || | ||
| 758 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | ||
| 759 | (vibration_device_handle.npad_type == NpadType::JoyconLeft || | ||
| 760 | vibration_device_handle.device_index == DeviceIndex::Left))) { | ||
| 761 | return; | ||
| 762 | } | ||
| 763 | |||
| 764 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 765 | if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && | ||
| 766 | vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { | ||
| 767 | return; | ||
| 768 | } | ||
| 769 | |||
| 770 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { | ||
| 771 | latest_vibration_values[npad_index][device_index] = vibration_value; | ||
| 676 | } | 772 | } |
| 677 | } | 773 | } |
| 678 | 774 | ||
| 679 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | 775 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 680 | return last_processed_vibration; | 776 | const std::vector<VibrationValue>& vibration_values) { |
| 777 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 778 | return; | ||
| 779 | } | ||
| 780 | |||
| 781 | ASSERT_OR_EXECUTE_MSG( | ||
| 782 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 783 | "The amount of device handles does not match with the amount of vibration values," | ||
| 784 | "this is undefined behavior!"); | ||
| 785 | |||
| 786 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 787 | VibrateController(vibration_device_handles[i], vibration_values[i]); | ||
| 788 | } | ||
| 789 | } | ||
| 790 | |||
| 791 | Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( | ||
| 792 | const DeviceHandle& vibration_device_handle) const { | ||
| 793 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 794 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 795 | return latest_vibration_values[npad_index][device_index]; | ||
| 796 | } | ||
| 797 | |||
| 798 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { | ||
| 799 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 800 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 801 | InitializeVibrationDeviceAtIndex(npad_index, device_index); | ||
| 802 | } | ||
| 803 | |||
| 804 | void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, | ||
| 805 | std::size_t device_index) { | ||
| 806 | if (vibrations[npad_index][device_index]) { | ||
| 807 | vibration_devices_mounted[npad_index][device_index] = | ||
| 808 | vibrations[npad_index][device_index]->GetStatus() == 1; | ||
| 809 | } else { | ||
| 810 | vibration_devices_mounted[npad_index][device_index] = false; | ||
| 811 | } | ||
| 812 | } | ||
| 813 | |||
| 814 | void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 815 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 816 | } | ||
| 817 | |||
| 818 | bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { | ||
| 819 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 820 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 821 | return vibration_devices_mounted[npad_index][device_index]; | ||
| 681 | } | 822 | } |
| 682 | 823 | ||
| 683 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 824 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| @@ -696,31 +837,38 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz | |||
| 696 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, | 837 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 697 | bool connected) { | 838 | bool connected) { |
| 698 | if (!connected) { | 839 | if (!connected) { |
| 699 | DisconnectNPadAtIndex(npad_index); | 840 | DisconnectNpadAtIndex(npad_index); |
| 700 | return; | 841 | return; |
| 701 | } | 842 | } |
| 702 | 843 | ||
| 703 | if (controller == NPadControllerType::Handheld) { | 844 | if (controller == NPadControllerType::Handheld) { |
| 704 | Settings::values.players[HANDHELD_INDEX].controller_type = | 845 | Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = |
| 705 | MapNPadToSettingsType(controller); | 846 | MapNPadToSettingsType(controller); |
| 706 | Settings::values.players[HANDHELD_INDEX].connected = true; | 847 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; |
| 707 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | 848 | connected_controllers[HANDHELD_INDEX] = {controller, true}; |
| 708 | InitNewlyAddedController(HANDHELD_INDEX); | 849 | InitNewlyAddedController(HANDHELD_INDEX); |
| 709 | return; | 850 | return; |
| 710 | } | 851 | } |
| 711 | 852 | ||
| 712 | Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); | 853 | Settings::values.players.GetValue()[npad_index].controller_type = |
| 713 | Settings::values.players[npad_index].connected = true; | 854 | MapNPadToSettingsType(controller); |
| 855 | Settings::values.players.GetValue()[npad_index].connected = true; | ||
| 714 | connected_controllers[npad_index] = {controller, true}; | 856 | connected_controllers[npad_index] = {controller, true}; |
| 715 | InitNewlyAddedController(npad_index); | 857 | InitNewlyAddedController(npad_index); |
| 716 | } | 858 | } |
| 717 | 859 | ||
| 718 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 860 | void Controller_NPad::DisconnectNpad(u32 npad_id) { |
| 719 | DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); | 861 | DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); |
| 720 | } | 862 | } |
| 721 | 863 | ||
| 722 | void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { | 864 | void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { |
| 723 | Settings::values.players[npad_index].connected = false; | 865 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { |
| 866 | // Send an empty vibration to stop any vibrations. | ||
| 867 | VibrateControllerAtIndex(npad_index, device_idx, {}); | ||
| 868 | vibration_devices_mounted[npad_index][device_idx] = false; | ||
| 869 | } | ||
| 870 | |||
| 871 | Settings::values.players.GetValue()[npad_index].connected = false; | ||
| 724 | connected_controllers[npad_index].is_connected = false; | 872 | connected_controllers[npad_index].is_connected = false; |
| 725 | 873 | ||
| 726 | auto& controller = shared_memory_entries[npad_index]; | 874 | auto& controller = shared_memory_entries[npad_index]; |
| @@ -758,7 +906,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { | |||
| 758 | (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && | 906 | (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && |
| 759 | connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { | 907 | connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { |
| 760 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. | 908 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. |
| 761 | DisconnectNPad(npad_id_2); | 909 | DisconnectNpad(npad_id_2); |
| 762 | AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); | 910 | AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); |
| 763 | } | 911 | } |
| 764 | } | 912 | } |
| @@ -830,14 +978,6 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot | |||
| 830 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; | 978 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; |
| 831 | } | 979 | } |
| 832 | 980 | ||
| 833 | void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { | ||
| 834 | can_controllers_vibrate = can_vibrate; | ||
| 835 | } | ||
| 836 | |||
| 837 | bool Controller_NPad::IsVibrationEnabled() const { | ||
| 838 | return can_controllers_vibrate; | ||
| 839 | } | ||
| 840 | |||
| 841 | void Controller_NPad::ClearAllConnectedControllers() { | 981 | void Controller_NPad::ClearAllConnectedControllers() { |
| 842 | for (auto& controller : connected_controllers) { | 982 | for (auto& controller : connected_controllers) { |
| 843 | if (controller.is_connected && controller.type != NPadControllerType::None) { | 983 | if (controller.is_connected && controller.type != NPadControllerType::None) { |
| @@ -882,7 +1022,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 882 | return false; | 1022 | return false; |
| 883 | } | 1023 | } |
| 884 | // Handheld should not be supported in docked mode | 1024 | // Handheld should not be supported in docked mode |
| 885 | if (Settings::values.use_docked_mode) { | 1025 | if (Settings::values.use_docked_mode.GetValue()) { |
| 886 | return false; | 1026 | return false; |
| 887 | } | 1027 | } |
| 888 | 1028 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index fd5c5a6eb..160dcbbe3 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -39,28 +39,30 @@ public: | |||
| 39 | // Called when input devices should be loaded | 39 | // Called when input devices should be loaded |
| 40 | void OnLoadInputDevices() override; | 40 | void OnLoadInputDevices() override; |
| 41 | 41 | ||
| 42 | struct NPadType { | 42 | enum class NPadControllerType { |
| 43 | union { | 43 | None, |
| 44 | u32_le raw{}; | 44 | ProController, |
| 45 | 45 | Handheld, | |
| 46 | BitField<0, 1, u32> pro_controller; | 46 | JoyDual, |
| 47 | BitField<1, 1, u32> handheld; | 47 | JoyLeft, |
| 48 | BitField<2, 1, u32> joycon_dual; | 48 | JoyRight, |
| 49 | BitField<3, 1, u32> joycon_left; | 49 | Pokeball, |
| 50 | BitField<4, 1, u32> joycon_right; | 50 | }; |
| 51 | 51 | ||
| 52 | BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible | 52 | enum class NpadType : u8 { |
| 53 | }; | 53 | ProController = 3, |
| 54 | Handheld = 4, | ||
| 55 | JoyconDual = 5, | ||
| 56 | JoyconLeft = 6, | ||
| 57 | JoyconRight = 7, | ||
| 58 | Pokeball = 9, | ||
| 54 | }; | 59 | }; |
| 55 | static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); | ||
| 56 | 60 | ||
| 57 | struct Vibration { | 61 | enum class DeviceIndex : u8 { |
| 58 | f32 amp_low; | 62 | Left = 0, |
| 59 | f32 freq_low; | 63 | Right = 1, |
| 60 | f32 amp_high; | 64 | None = 2, |
| 61 | f32 freq_high; | ||
| 62 | }; | 65 | }; |
| 63 | static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); | ||
| 64 | 66 | ||
| 65 | enum class GyroscopeZeroDriftMode : u32 { | 67 | enum class GyroscopeZeroDriftMode : u32 { |
| 66 | Loose = 0, | 68 | Loose = 0, |
| @@ -73,7 +75,7 @@ public: | |||
| 73 | Horizontal = 1, | 75 | Horizontal = 1, |
| 74 | }; | 76 | }; |
| 75 | 77 | ||
| 76 | enum class NPadAssignments : u32_le { | 78 | enum class NpadAssignments : u32 { |
| 77 | Dual = 0, | 79 | Dual = 0, |
| 78 | Single = 1, | 80 | Single = 1, |
| 79 | }; | 81 | }; |
| @@ -84,15 +86,36 @@ public: | |||
| 84 | None = 2, | 86 | None = 2, |
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | enum class NPadControllerType { | 89 | struct DeviceHandle { |
| 88 | None, | 90 | NpadType npad_type{}; |
| 89 | ProController, | 91 | u8 npad_id{}; |
| 90 | Handheld, | 92 | DeviceIndex device_index{}; |
| 91 | JoyDual, | 93 | INSERT_PADDING_BYTES(1); |
| 92 | JoyLeft, | 94 | }; |
| 93 | JoyRight, | 95 | static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); |
| 94 | Pokeball, | 96 | |
| 97 | struct NpadStyleSet { | ||
| 98 | union { | ||
| 99 | u32_le raw{}; | ||
| 100 | |||
| 101 | BitField<0, 1, u32> pro_controller; | ||
| 102 | BitField<1, 1, u32> handheld; | ||
| 103 | BitField<2, 1, u32> joycon_dual; | ||
| 104 | BitField<3, 1, u32> joycon_left; | ||
| 105 | BitField<4, 1, u32> joycon_right; | ||
| 106 | |||
| 107 | BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible | ||
| 108 | }; | ||
| 109 | }; | ||
| 110 | static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); | ||
| 111 | |||
| 112 | struct VibrationValue { | ||
| 113 | f32 amp_low{0.0f}; | ||
| 114 | f32 freq_low{160.0f}; | ||
| 115 | f32 amp_high{0.0f}; | ||
| 116 | f32 freq_high{320.0f}; | ||
| 95 | }; | 117 | }; |
| 118 | static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); | ||
| 96 | 119 | ||
| 97 | struct LedPattern { | 120 | struct LedPattern { |
| 98 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | 121 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { |
| @@ -110,12 +133,12 @@ public: | |||
| 110 | }; | 133 | }; |
| 111 | }; | 134 | }; |
| 112 | 135 | ||
| 113 | void SetSupportedStyleSet(NPadType style_set); | 136 | void SetSupportedStyleSet(NpadStyleSet style_set); |
| 114 | NPadType GetSupportedStyleSet() const; | 137 | NpadStyleSet GetSupportedStyleSet() const; |
| 115 | 138 | ||
| 116 | void SetSupportedNPadIdTypes(u8* data, std::size_t length); | 139 | void SetSupportedNpadIdTypes(u8* data, std::size_t length); |
| 117 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); | 140 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); |
| 118 | std::size_t GetSupportedNPadIdTypesSize() const; | 141 | std::size_t GetSupportedNpadIdTypesSize() const; |
| 119 | 142 | ||
| 120 | void SetHoldType(NpadHoldType joy_hold_type); | 143 | void SetHoldType(NpadHoldType joy_hold_type); |
| 121 | NpadHoldType GetHoldType() const; | 144 | NpadHoldType GetHoldType() const; |
| @@ -123,12 +146,26 @@ public: | |||
| 123 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); | 146 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); |
| 124 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; | 147 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; |
| 125 | 148 | ||
| 126 | void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); | 149 | void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); |
| 150 | |||
| 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | ||
| 152 | const VibrationValue& vibration_value); | ||
| 153 | |||
| 154 | void VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 155 | const VibrationValue& vibration_value); | ||
| 156 | |||
| 157 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | ||
| 158 | const std::vector<VibrationValue>& vibration_values); | ||
| 159 | |||
| 160 | VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; | ||
| 161 | |||
| 162 | void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); | ||
| 163 | |||
| 164 | void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); | ||
| 127 | 165 | ||
| 128 | void VibrateController(const std::vector<u32>& controllers, | 166 | void SetPermitVibrationSession(bool permit_vibration_session); |
| 129 | const std::vector<Vibration>& vibrations); | ||
| 130 | 167 | ||
| 131 | Vibration GetLastVibration() const; | 168 | bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; |
| 132 | 169 | ||
| 133 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 170 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; |
| 134 | void SignalStyleSetChangedEvent(u32 npad_id) const; | 171 | void SignalStyleSetChangedEvent(u32 npad_id) const; |
| @@ -138,8 +175,8 @@ public: | |||
| 138 | // Adds a new controller at an index with connection status. | 175 | // Adds a new controller at an index with connection status. |
| 139 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | 176 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); |
| 140 | 177 | ||
| 141 | void DisconnectNPad(u32 npad_id); | 178 | void DisconnectNpad(u32 npad_id); |
| 142 | void DisconnectNPadAtIndex(std::size_t index); | 179 | void DisconnectNpadAtIndex(std::size_t index); |
| 143 | 180 | ||
| 144 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 181 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 145 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 182 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| @@ -148,8 +185,6 @@ public: | |||
| 148 | LedPattern GetLedPattern(u32 npad_id); | 185 | LedPattern GetLedPattern(u32 npad_id); |
| 149 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; | 186 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; |
| 150 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); | 187 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); |
| 151 | void SetVibrationEnabled(bool can_vibrate); | ||
| 152 | bool IsVibrationEnabled() const; | ||
| 153 | void ClearAllConnectedControllers(); | 188 | void ClearAllConnectedControllers(); |
| 154 | void DisconnectAllConnectedControllers(); | 189 | void DisconnectAllConnectedControllers(); |
| 155 | void ConnectAllDisconnectedControllers(); | 190 | void ConnectAllDisconnectedControllers(); |
| @@ -324,8 +359,8 @@ private: | |||
| 324 | }; | 359 | }; |
| 325 | 360 | ||
| 326 | struct NPadEntry { | 361 | struct NPadEntry { |
| 327 | NPadType joy_styles; | 362 | NpadStyleSet joy_styles; |
| 328 | NPadAssignments pad_assignment; | 363 | NpadAssignments pad_assignment; |
| 329 | 364 | ||
| 330 | ColorReadError single_color_error; | 365 | ColorReadError single_color_error; |
| 331 | ControllerColor single_color; | 366 | ControllerColor single_color; |
| @@ -368,7 +403,7 @@ private: | |||
| 368 | 403 | ||
| 369 | u32 press_state{}; | 404 | u32 press_state{}; |
| 370 | 405 | ||
| 371 | NPadType style{}; | 406 | NpadStyleSet style{}; |
| 372 | std::array<NPadEntry, 10> shared_memory_entries{}; | 407 | std::array<NPadEntry, 10> shared_memory_entries{}; |
| 373 | using ButtonArray = std::array< | 408 | using ButtonArray = std::array< |
| 374 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, | 409 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, |
| @@ -376,22 +411,28 @@ private: | |||
| 376 | using StickArray = std::array< | 411 | using StickArray = std::array< |
| 377 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>, | 412 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>, |
| 378 | 10>; | 413 | 10>; |
| 414 | using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>, | ||
| 415 | Settings::NativeVibration::NUM_VIBRATIONS_HID>, | ||
| 416 | 10>; | ||
| 379 | using MotionArray = std::array< | 417 | using MotionArray = std::array< |
| 380 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>, | 418 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>, |
| 381 | 10>; | 419 | 10>; |
| 382 | ButtonArray buttons; | 420 | ButtonArray buttons; |
| 383 | StickArray sticks; | 421 | StickArray sticks; |
| 422 | VibrationArray vibrations; | ||
| 384 | MotionArray motions; | 423 | MotionArray motions; |
| 385 | std::vector<u32> supported_npad_id_types{}; | 424 | std::vector<u32> supported_npad_id_types{}; |
| 386 | NpadHoldType hold_type{NpadHoldType::Vertical}; | 425 | NpadHoldType hold_type{NpadHoldType::Vertical}; |
| 387 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 426 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 388 | // Each controller should have their own styleset changed event | 427 | // Each controller should have their own styleset changed event |
| 389 | std::array<Kernel::EventPair, 10> styleset_changed_events; | 428 | std::array<Kernel::EventPair, 10> styleset_changed_events; |
| 390 | Vibration last_processed_vibration{}; | 429 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; |
| 430 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | ||
| 431 | bool permit_vibration_session_enabled{false}; | ||
| 432 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | ||
| 391 | std::array<ControllerHolder, 10> connected_controllers{}; | 433 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 392 | std::array<bool, 10> unintended_home_button_input_protection{}; | 434 | std::array<bool, 10> unintended_home_button_input_protection{}; |
| 393 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | 435 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; |
| 394 | bool can_controllers_vibrate{true}; | ||
| 395 | bool sixaxis_sensors_enabled{true}; | 436 | bool sixaxis_sensors_enabled{true}; |
| 396 | bool sixaxis_at_rest{true}; | 437 | bool sixaxis_at_rest{true}; |
| 397 | std::array<ControllerPad, 10> npad_pad_states{}; | 438 | std::array<ControllerPad, 10> npad_pad_states{}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 50f709b25..902516b29 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -139,20 +139,34 @@ void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose | |||
| 139 | 139 | ||
| 140 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { | 140 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { |
| 141 | public: | 141 | public: |
| 142 | IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") { | 142 | explicit IActiveVibrationDeviceList(std::shared_ptr<IAppletResource> applet_resource_) |
| 143 | : ServiceFramework("IActiveVibrationDeviceList"), applet_resource(applet_resource_) { | ||
| 144 | // clang-format off | ||
| 143 | static const FunctionInfo functions[] = { | 145 | static const FunctionInfo functions[] = { |
| 144 | {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, | 146 | {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, |
| 145 | }; | 147 | }; |
| 148 | // clang-format on | ||
| 149 | |||
| 146 | RegisterHandlers(functions); | 150 | RegisterHandlers(functions); |
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | private: | 153 | private: |
| 150 | void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) { | 154 | void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { |
| 151 | LOG_WARNING(Service_HID, "(STUBBED) called"); | 155 | IPC::RequestParser rp{ctx}; |
| 156 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; | ||
| 157 | |||
| 158 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 159 | .InitializeVibrationDevice(vibration_device_handle); | ||
| 160 | |||
| 161 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", | ||
| 162 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, | ||
| 163 | vibration_device_handle.device_index); | ||
| 152 | 164 | ||
| 153 | IPC::ResponseBuilder rb{ctx, 2}; | 165 | IPC::ResponseBuilder rb{ctx, 2}; |
| 154 | rb.Push(RESULT_SUCCESS); | 166 | rb.Push(RESULT_SUCCESS); |
| 155 | } | 167 | } |
| 168 | |||
| 169 | std::shared_ptr<IAppletResource> applet_resource; | ||
| 156 | }; | 170 | }; |
| 157 | 171 | ||
| 158 | std::shared_ptr<IAppletResource> Hid::GetAppletResource() { | 172 | std::shared_ptr<IAppletResource> Hid::GetAppletResource() { |
| @@ -241,7 +255,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 241 | {208, nullptr, "GetActualVibrationGcErmCommand"}, | 255 | {208, nullptr, "GetActualVibrationGcErmCommand"}, |
| 242 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, | 256 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 243 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, | 257 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 244 | {211, nullptr, "IsVibrationDeviceMounted"}, | 258 | {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, |
| 245 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 259 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 246 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 260 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 247 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, | 261 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| @@ -320,142 +334,152 @@ void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { | |||
| 320 | rb.PushIpcInterface<IAppletResource>(applet_resource); | 334 | rb.PushIpcInterface<IAppletResource>(applet_resource); |
| 321 | } | 335 | } |
| 322 | 336 | ||
| 323 | void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { | 337 | void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { |
| 324 | IPC::RequestParser rp{ctx}; | 338 | IPC::RequestParser rp{ctx}; |
| 325 | const auto basic_xpad_id{rp.Pop<u32>()}; | ||
| 326 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 339 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 327 | 340 | ||
| 328 | LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", basic_xpad_id, | 341 | applet_resource->ActivateController(HidController::DebugPad); |
| 329 | applet_resource_user_id); | 342 | |
| 343 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 330 | 344 | ||
| 331 | applet_resource->ActivateController(HidController::XPad); | ||
| 332 | IPC::ResponseBuilder rb{ctx, 2}; | 345 | IPC::ResponseBuilder rb{ctx, 2}; |
| 333 | rb.Push(RESULT_SUCCESS); | 346 | rb.Push(RESULT_SUCCESS); |
| 334 | } | 347 | } |
| 335 | 348 | ||
| 336 | void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { | 349 | void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { |
| 337 | IPC::RequestParser rp{ctx}; | 350 | IPC::RequestParser rp{ctx}; |
| 338 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 351 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 339 | 352 | ||
| 340 | LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); | 353 | applet_resource->ActivateController(HidController::Touchscreen); |
| 341 | |||
| 342 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 343 | rb.Push(RESULT_SUCCESS); | ||
| 344 | rb.Push(0); | ||
| 345 | } | ||
| 346 | 354 | ||
| 347 | void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { | 355 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 348 | IPC::RequestParser rp{ctx}; | ||
| 349 | const auto handle{rp.Pop<u32>()}; | ||
| 350 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 351 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); | ||
| 352 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | ||
| 353 | applet_resource_user_id); | ||
| 354 | 356 | ||
| 355 | IPC::ResponseBuilder rb{ctx, 2}; | 357 | IPC::ResponseBuilder rb{ctx, 2}; |
| 356 | rb.Push(RESULT_SUCCESS); | 358 | rb.Push(RESULT_SUCCESS); |
| 357 | } | 359 | } |
| 358 | 360 | ||
| 359 | void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { | 361 | void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { |
| 360 | IPC::RequestParser rp{ctx}; | 362 | IPC::RequestParser rp{ctx}; |
| 361 | const auto handle{rp.Pop<u32>()}; | ||
| 362 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 363 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 363 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 364 | 364 | ||
| 365 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 365 | applet_resource->ActivateController(HidController::Mouse); |
| 366 | applet_resource_user_id); | 366 | |
| 367 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 367 | 368 | ||
| 368 | IPC::ResponseBuilder rb{ctx, 2}; | 369 | IPC::ResponseBuilder rb{ctx, 2}; |
| 369 | rb.Push(RESULT_SUCCESS); | 370 | rb.Push(RESULT_SUCCESS); |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { | 373 | void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { |
| 373 | IPC::RequestParser rp{ctx}; | 374 | IPC::RequestParser rp{ctx}; |
| 374 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 375 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 375 | 376 | ||
| 377 | applet_resource->ActivateController(HidController::Keyboard); | ||
| 378 | |||
| 376 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 379 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 377 | 380 | ||
| 378 | applet_resource->ActivateController(HidController::DebugPad); | ||
| 379 | IPC::ResponseBuilder rb{ctx, 2}; | 381 | IPC::ResponseBuilder rb{ctx, 2}; |
| 380 | rb.Push(RESULT_SUCCESS); | 382 | rb.Push(RESULT_SUCCESS); |
| 381 | } | 383 | } |
| 382 | 384 | ||
| 383 | void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { | 385 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { |
| 384 | IPC::RequestParser rp{ctx}; | 386 | IPC::RequestParser rp{ctx}; |
| 385 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 387 | const auto flags{rp.Pop<u32>()}; |
| 386 | 388 | ||
| 387 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 389 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); |
| 388 | 390 | ||
| 389 | applet_resource->ActivateController(HidController::Touchscreen); | ||
| 390 | IPC::ResponseBuilder rb{ctx, 2}; | 391 | IPC::ResponseBuilder rb{ctx, 2}; |
| 391 | rb.Push(RESULT_SUCCESS); | 392 | rb.Push(RESULT_SUCCESS); |
| 392 | } | 393 | } |
| 393 | 394 | ||
| 394 | void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { | 395 | void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { |
| 395 | IPC::RequestParser rp{ctx}; | 396 | IPC::RequestParser rp{ctx}; |
| 396 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 397 | struct Parameters { |
| 398 | u32 basic_xpad_id{}; | ||
| 399 | INSERT_PADDING_WORDS(1); | ||
| 400 | u64 applet_resource_user_id{}; | ||
| 401 | }; | ||
| 397 | 402 | ||
| 398 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 403 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 404 | |||
| 405 | applet_resource->ActivateController(HidController::XPad); | ||
| 406 | |||
| 407 | LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", | ||
| 408 | parameters.basic_xpad_id, parameters.applet_resource_user_id); | ||
| 399 | 409 | ||
| 400 | applet_resource->ActivateController(HidController::Mouse); | ||
| 401 | IPC::ResponseBuilder rb{ctx, 2}; | 410 | IPC::ResponseBuilder rb{ctx, 2}; |
| 402 | rb.Push(RESULT_SUCCESS); | 411 | rb.Push(RESULT_SUCCESS); |
| 403 | } | 412 | } |
| 404 | 413 | ||
| 405 | void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { | 414 | void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { |
| 406 | IPC::RequestParser rp{ctx}; | 415 | IPC::RequestParser rp{ctx}; |
| 407 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 416 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 408 | 417 | ||
| 409 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 418 | LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); |
| 410 | 419 | ||
| 411 | applet_resource->ActivateController(HidController::Keyboard); | 420 | IPC::ResponseBuilder rb{ctx, 3}; |
| 412 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 413 | rb.Push(RESULT_SUCCESS); | 421 | rb.Push(RESULT_SUCCESS); |
| 422 | rb.Push(0); | ||
| 414 | } | 423 | } |
| 415 | 424 | ||
| 416 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | 425 | void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 417 | IPC::RequestParser rp{ctx}; | 426 | IPC::RequestParser rp{ctx}; |
| 418 | const auto flags{rp.Pop<u32>()}; | 427 | struct Parameters { |
| 419 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | 428 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 429 | INSERT_PADDING_WORDS(1); | ||
| 430 | u64 applet_resource_user_id{}; | ||
| 431 | }; | ||
| 420 | 432 | ||
| 421 | IPC::ResponseBuilder rb{ctx, 2}; | 433 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 422 | rb.Push(RESULT_SUCCESS); | ||
| 423 | } | ||
| 424 | 434 | ||
| 425 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | 435 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); |
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | const auto unknown{rp.Pop<u32>()}; | ||
| 428 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 429 | 436 | ||
| 430 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, | 437 | LOG_DEBUG(Service_HID, |
| 431 | applet_resource_user_id); | 438 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 439 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 440 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 432 | 441 | ||
| 433 | applet_resource->ActivateController(HidController::Gesture); | ||
| 434 | IPC::ResponseBuilder rb{ctx, 2}; | 442 | IPC::ResponseBuilder rb{ctx, 2}; |
| 435 | rb.Push(RESULT_SUCCESS); | 443 | rb.Push(RESULT_SUCCESS); |
| 436 | } | 444 | } |
| 437 | 445 | ||
| 438 | void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { | 446 | void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 439 | // Should have no effect with how our npad sets up the data | ||
| 440 | IPC::RequestParser rp{ctx}; | 447 | IPC::RequestParser rp{ctx}; |
| 441 | const auto unknown{rp.Pop<u32>()}; | 448 | struct Parameters { |
| 442 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 449 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 450 | INSERT_PADDING_WORDS(1); | ||
| 451 | u64 applet_resource_user_id{}; | ||
| 452 | }; | ||
| 443 | 453 | ||
| 444 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, | 454 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 445 | applet_resource_user_id); | 455 | |
| 456 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 457 | |||
| 458 | LOG_DEBUG(Service_HID, | ||
| 459 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 460 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 461 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 446 | 462 | ||
| 447 | applet_resource->ActivateController(HidController::NPad); | ||
| 448 | IPC::ResponseBuilder rb{ctx, 2}; | 463 | IPC::ResponseBuilder rb{ctx, 2}; |
| 449 | rb.Push(RESULT_SUCCESS); | 464 | rb.Push(RESULT_SUCCESS); |
| 450 | } | 465 | } |
| 451 | 466 | ||
| 452 | void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | 467 | void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 453 | IPC::RequestParser rp{ctx}; | 468 | IPC::RequestParser rp{ctx}; |
| 454 | const auto handle{rp.Pop<u32>()}; | 469 | struct Parameters { |
| 455 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 470 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 471 | INSERT_PADDING_WORDS(1); | ||
| 472 | u64 applet_resource_user_id{}; | ||
| 473 | }; | ||
| 456 | 474 | ||
| 457 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 475 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 458 | applet_resource_user_id); | 476 | |
| 477 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); | ||
| 478 | |||
| 479 | LOG_DEBUG(Service_HID, | ||
| 480 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 481 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 482 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 459 | 483 | ||
| 460 | IPC::ResponseBuilder rb{ctx, 2}; | 484 | IPC::ResponseBuilder rb{ctx, 2}; |
| 461 | rb.Push(RESULT_SUCCESS); | 485 | rb.Push(RESULT_SUCCESS); |
| @@ -463,11 +487,20 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 463 | 487 | ||
| 464 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | 488 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 465 | IPC::RequestParser rp{ctx}; | 489 | IPC::RequestParser rp{ctx}; |
| 466 | const auto handle{rp.Pop<u32>()}; | 490 | struct Parameters { |
| 467 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 491 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 492 | INSERT_PADDING_WORDS(1); | ||
| 493 | u64 applet_resource_user_id{}; | ||
| 494 | }; | ||
| 468 | 495 | ||
| 469 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 496 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 470 | applet_resource_user_id); | 497 | |
| 498 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 499 | |||
| 500 | LOG_DEBUG(Service_HID, | ||
| 501 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 502 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 503 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 471 | 504 | ||
| 472 | IPC::ResponseBuilder rb{ctx, 2}; | 505 | IPC::ResponseBuilder rb{ctx, 2}; |
| 473 | rb.Push(RESULT_SUCCESS); | 506 | rb.Push(RESULT_SUCCESS); |
| @@ -475,12 +508,21 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 475 | 508 | ||
| 476 | void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { | 509 | void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { |
| 477 | IPC::RequestParser rp{ctx}; | 510 | IPC::RequestParser rp{ctx}; |
| 478 | [[maybe_unused]] const auto enable{rp.Pop<bool>()}; | 511 | struct Parameters { |
| 479 | const auto handle{rp.Pop<u32>()}; | 512 | bool enable_sixaxis_sensor_fusion{}; |
| 480 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 513 | INSERT_PADDING_BYTES(3); |
| 514 | Controller_NPad::DeviceHandle sixaxis_handle{}; | ||
| 515 | u64 applet_resource_user_id{}; | ||
| 516 | }; | ||
| 481 | 517 | ||
| 482 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 518 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 483 | applet_resource_user_id); | 519 | |
| 520 | LOG_WARNING(Service_HID, | ||
| 521 | "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " | ||
| 522 | "device_index={}, applet_resource_user_id={}", | ||
| 523 | parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, | ||
| 524 | parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, | ||
| 525 | parameters.applet_resource_user_id); | ||
| 484 | 526 | ||
| 485 | IPC::ResponseBuilder rb{ctx, 2}; | 527 | IPC::ResponseBuilder rb{ctx, 2}; |
| 486 | rb.Push(RESULT_SUCCESS); | 528 | rb.Push(RESULT_SUCCESS); |
| @@ -488,14 +530,17 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { | |||
| 488 | 530 | ||
| 489 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 531 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 490 | IPC::RequestParser rp{ctx}; | 532 | IPC::RequestParser rp{ctx}; |
| 491 | const auto handle{rp.Pop<u32>()}; | 533 | const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
| 492 | const auto drift_mode{rp.Pop<u32>()}; | 534 | const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; |
| 493 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 535 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 494 | 536 | ||
| 495 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 537 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 496 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode{drift_mode}); | 538 | .SetGyroscopeZeroDriftMode(drift_mode); |
| 497 | 539 | ||
| 498 | LOG_DEBUG(Service_HID, "called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, | 540 | LOG_DEBUG(Service_HID, |
| 541 | "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " | ||
| 542 | "applet_resource_user_id={}", | ||
| 543 | sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index, | ||
| 499 | drift_mode, applet_resource_user_id); | 544 | drift_mode, applet_resource_user_id); |
| 500 | 545 | ||
| 501 | IPC::ResponseBuilder rb{ctx, 2}; | 546 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -504,29 +549,42 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | |||
| 504 | 549 | ||
| 505 | void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 550 | void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 506 | IPC::RequestParser rp{ctx}; | 551 | IPC::RequestParser rp{ctx}; |
| 507 | const auto handle{rp.Pop<u32>()}; | 552 | struct Parameters { |
| 508 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 553 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 554 | INSERT_PADDING_WORDS(1); | ||
| 555 | u64 applet_resource_user_id{}; | ||
| 556 | }; | ||
| 557 | |||
| 558 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 509 | 559 | ||
| 510 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 560 | LOG_DEBUG(Service_HID, |
| 511 | applet_resource_user_id); | 561 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 562 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 563 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 512 | 564 | ||
| 513 | IPC::ResponseBuilder rb{ctx, 3}; | 565 | IPC::ResponseBuilder rb{ctx, 3}; |
| 514 | rb.Push(RESULT_SUCCESS); | 566 | rb.Push(RESULT_SUCCESS); |
| 515 | rb.Push<u32>( | 567 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 516 | static_cast<u32>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 568 | .GetGyroscopeZeroDriftMode()); |
| 517 | .GetGyroscopeZeroDriftMode())); | ||
| 518 | } | 569 | } |
| 519 | 570 | ||
| 520 | void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 571 | void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 521 | IPC::RequestParser rp{ctx}; | 572 | IPC::RequestParser rp{ctx}; |
| 522 | const auto handle{rp.Pop<u32>()}; | 573 | struct Parameters { |
| 523 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 574 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 575 | INSERT_PADDING_WORDS(1); | ||
| 576 | u64 applet_resource_user_id{}; | ||
| 577 | }; | ||
| 578 | |||
| 579 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 524 | 580 | ||
| 525 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 581 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 526 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); | 582 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); |
| 527 | 583 | ||
| 528 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 584 | LOG_DEBUG(Service_HID, |
| 529 | applet_resource_user_id); | 585 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 586 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 587 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 530 | 588 | ||
| 531 | IPC::ResponseBuilder rb{ctx, 2}; | 589 | IPC::ResponseBuilder rb{ctx, 2}; |
| 532 | rb.Push(RESULT_SUCCESS); | 590 | rb.Push(RESULT_SUCCESS); |
| @@ -534,11 +592,18 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | |||
| 534 | 592 | ||
| 535 | void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { | 593 | void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { |
| 536 | IPC::RequestParser rp{ctx}; | 594 | IPC::RequestParser rp{ctx}; |
| 537 | const auto handle{rp.Pop<u32>()}; | 595 | struct Parameters { |
| 538 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 596 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 597 | INSERT_PADDING_WORDS(1); | ||
| 598 | u64 applet_resource_user_id{}; | ||
| 599 | }; | ||
| 600 | |||
| 601 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 539 | 602 | ||
| 540 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 603 | LOG_DEBUG(Service_HID, |
| 541 | applet_resource_user_id); | 604 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 605 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 606 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 542 | 607 | ||
| 543 | IPC::ResponseBuilder rb{ctx, 3}; | 608 | IPC::ResponseBuilder rb{ctx, 3}; |
| 544 | rb.Push(RESULT_SUCCESS); | 609 | rb.Push(RESULT_SUCCESS); |
| @@ -546,15 +611,34 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { | |||
| 546 | .IsSixAxisSensorAtRest()); | 611 | .IsSixAxisSensorAtRest()); |
| 547 | } | 612 | } |
| 548 | 613 | ||
| 614 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | ||
| 615 | IPC::RequestParser rp{ctx}; | ||
| 616 | struct Parameters { | ||
| 617 | u32 unknown{}; | ||
| 618 | INSERT_PADDING_WORDS(1); | ||
| 619 | u64 applet_resource_user_id{}; | ||
| 620 | }; | ||
| 621 | |||
| 622 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 623 | |||
| 624 | applet_resource->ActivateController(HidController::Gesture); | ||
| 625 | |||
| 626 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, | ||
| 627 | parameters.applet_resource_user_id); | ||
| 628 | |||
| 629 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 630 | rb.Push(RESULT_SUCCESS); | ||
| 631 | } | ||
| 632 | |||
| 549 | void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { | 633 | void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { |
| 550 | IPC::RequestParser rp{ctx}; | 634 | IPC::RequestParser rp{ctx}; |
| 551 | const auto supported_styleset{rp.Pop<u32>()}; | 635 | const auto supported_styleset{rp.Pop<u32>()}; |
| 552 | 636 | ||
| 553 | LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); | ||
| 554 | |||
| 555 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 637 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 556 | .SetSupportedStyleSet({supported_styleset}); | 638 | .SetSupportedStyleSet({supported_styleset}); |
| 557 | 639 | ||
| 640 | LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); | ||
| 641 | |||
| 558 | IPC::ResponseBuilder rb{ctx, 2}; | 642 | IPC::ResponseBuilder rb{ctx, 2}; |
| 559 | rb.Push(RESULT_SUCCESS); | 643 | rb.Push(RESULT_SUCCESS); |
| 560 | } | 644 | } |
| @@ -565,21 +649,22 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { | |||
| 565 | 649 | ||
| 566 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 650 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 567 | 651 | ||
| 568 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 569 | |||
| 570 | IPC::ResponseBuilder rb{ctx, 3}; | 652 | IPC::ResponseBuilder rb{ctx, 3}; |
| 571 | rb.Push(RESULT_SUCCESS); | 653 | rb.Push(RESULT_SUCCESS); |
| 572 | rb.Push<u32>(controller.GetSupportedStyleSet().raw); | 654 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 655 | .GetSupportedStyleSet() | ||
| 656 | .raw); | ||
| 573 | } | 657 | } |
| 574 | 658 | ||
| 575 | void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { | 659 | void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { |
| 576 | IPC::RequestParser rp{ctx}; | 660 | IPC::RequestParser rp{ctx}; |
| 577 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 661 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 578 | 662 | ||
| 663 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 664 | .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||
| 665 | |||
| 579 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 666 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 580 | 667 | ||
| 581 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 582 | .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||
| 583 | IPC::ResponseBuilder rb{ctx, 2}; | 668 | IPC::ResponseBuilder rb{ctx, 2}; |
| 584 | rb.Push(RESULT_SUCCESS); | 669 | rb.Push(RESULT_SUCCESS); |
| 585 | } | 670 | } |
| @@ -588,48 +673,62 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { | |||
| 588 | IPC::RequestParser rp{ctx}; | 673 | IPC::RequestParser rp{ctx}; |
| 589 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 674 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 590 | 675 | ||
| 676 | applet_resource->ActivateController(HidController::NPad); | ||
| 677 | |||
| 591 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 678 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 592 | 679 | ||
| 593 | IPC::ResponseBuilder rb{ctx, 2}; | 680 | IPC::ResponseBuilder rb{ctx, 2}; |
| 594 | rb.Push(RESULT_SUCCESS); | 681 | rb.Push(RESULT_SUCCESS); |
| 595 | applet_resource->ActivateController(HidController::NPad); | ||
| 596 | } | 682 | } |
| 597 | 683 | ||
| 598 | void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { | 684 | void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { |
| 599 | IPC::RequestParser rp{ctx}; | 685 | IPC::RequestParser rp{ctx}; |
| 600 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 686 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 601 | 687 | ||
| 688 | applet_resource->DeactivateController(HidController::NPad); | ||
| 689 | |||
| 602 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 690 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 603 | 691 | ||
| 604 | IPC::ResponseBuilder rb{ctx, 2}; | 692 | IPC::ResponseBuilder rb{ctx, 2}; |
| 605 | rb.Push(RESULT_SUCCESS); | 693 | rb.Push(RESULT_SUCCESS); |
| 606 | applet_resource->DeactivateController(HidController::NPad); | ||
| 607 | } | 694 | } |
| 608 | 695 | ||
| 609 | void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { | 696 | void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { |
| 610 | IPC::RequestParser rp{ctx}; | 697 | IPC::RequestParser rp{ctx}; |
| 611 | const auto npad_id{rp.Pop<u32>()}; | 698 | struct Parameters { |
| 612 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 699 | u32 npad_id{}; |
| 613 | const auto unknown{rp.Pop<u64>()}; | 700 | INSERT_PADDING_WORDS(1); |
| 701 | u64 applet_resource_user_id{}; | ||
| 702 | u64 unknown{}; | ||
| 703 | }; | ||
| 614 | 704 | ||
| 615 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, | 705 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 616 | applet_resource_user_id, unknown); | 706 | |
| 707 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", | ||
| 708 | parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); | ||
| 617 | 709 | ||
| 618 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 710 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 619 | rb.Push(RESULT_SUCCESS); | 711 | rb.Push(RESULT_SUCCESS); |
| 620 | rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 712 | rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 621 | .GetStyleSetChangedEvent(npad_id)); | 713 | .GetStyleSetChangedEvent(parameters.npad_id)); |
| 622 | } | 714 | } |
| 623 | 715 | ||
| 624 | void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { | 716 | void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { |
| 625 | IPC::RequestParser rp{ctx}; | 717 | IPC::RequestParser rp{ctx}; |
| 626 | const auto npad_id{rp.Pop<u32>()}; | 718 | struct Parameters { |
| 627 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 719 | u32 npad_id{}; |
| 720 | INSERT_PADDING_WORDS(1); | ||
| 721 | u64 applet_resource_user_id{}; | ||
| 722 | }; | ||
| 628 | 723 | ||
| 629 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, | 724 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 630 | applet_resource_user_id); | 725 | |
| 726 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 727 | .DisconnectNpad(parameters.npad_id); | ||
| 728 | |||
| 729 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, | ||
| 730 | parameters.applet_resource_user_id); | ||
| 631 | 731 | ||
| 632 | applet_resource->GetController<Controller_NPad>(HidController::NPad).DisconnectNPad(npad_id); | ||
| 633 | IPC::ResponseBuilder rb{ctx, 2}; | 732 | IPC::ResponseBuilder rb{ctx, 2}; |
| 634 | rb.Push(RESULT_SUCCESS); | 733 | rb.Push(RESULT_SUCCESS); |
| 635 | } | 734 | } |
| @@ -642,22 +741,41 @@ void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { | |||
| 642 | 741 | ||
| 643 | IPC::ResponseBuilder rb{ctx, 4}; | 742 | IPC::ResponseBuilder rb{ctx, 4}; |
| 644 | rb.Push(RESULT_SUCCESS); | 743 | rb.Push(RESULT_SUCCESS); |
| 645 | rb.PushRaw<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 744 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 646 | .GetLedPattern(npad_id) | 745 | .GetLedPattern(npad_id) |
| 647 | .raw); | 746 | .raw); |
| 747 | } | ||
| 748 | |||
| 749 | void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { | ||
| 750 | // Should have no effect with how our npad sets up the data | ||
| 751 | IPC::RequestParser rp{ctx}; | ||
| 752 | struct Parameters { | ||
| 753 | u32 unknown{}; | ||
| 754 | INSERT_PADDING_WORDS(1); | ||
| 755 | u64 applet_resource_user_id{}; | ||
| 756 | }; | ||
| 757 | |||
| 758 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 759 | |||
| 760 | applet_resource->ActivateController(HidController::NPad); | ||
| 761 | |||
| 762 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, | ||
| 763 | parameters.applet_resource_user_id); | ||
| 764 | |||
| 765 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 766 | rb.Push(RESULT_SUCCESS); | ||
| 648 | } | 767 | } |
| 649 | 768 | ||
| 650 | void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { | 769 | void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { |
| 651 | IPC::RequestParser rp{ctx}; | 770 | IPC::RequestParser rp{ctx}; |
| 652 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 771 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 653 | const auto hold_type{rp.Pop<u64>()}; | 772 | const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()}; |
| 773 | |||
| 774 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type); | ||
| 654 | 775 | ||
| 655 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", | 776 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", |
| 656 | applet_resource_user_id, hold_type); | 777 | applet_resource_user_id, hold_type); |
| 657 | 778 | ||
| 658 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 659 | controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); | ||
| 660 | |||
| 661 | IPC::ResponseBuilder rb{ctx, 2}; | 779 | IPC::ResponseBuilder rb{ctx, 2}; |
| 662 | rb.Push(RESULT_SUCCESS); | 780 | rb.Push(RESULT_SUCCESS); |
| 663 | } | 781 | } |
| @@ -668,22 +786,26 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { | |||
| 668 | 786 | ||
| 669 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 787 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 670 | 788 | ||
| 671 | const auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 672 | IPC::ResponseBuilder rb{ctx, 4}; | 789 | IPC::ResponseBuilder rb{ctx, 4}; |
| 673 | rb.Push(RESULT_SUCCESS); | 790 | rb.Push(RESULT_SUCCESS); |
| 674 | rb.Push<u64>(static_cast<u64>(controller.GetHoldType())); | 791 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType()); |
| 675 | } | 792 | } |
| 676 | 793 | ||
| 677 | void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { | 794 | void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { |
| 678 | IPC::RequestParser rp{ctx}; | 795 | IPC::RequestParser rp{ctx}; |
| 679 | const auto npad_id{rp.Pop<u32>()}; | 796 | struct Parameters { |
| 680 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 797 | u32 npad_id{}; |
| 798 | INSERT_PADDING_WORDS(1); | ||
| 799 | u64 applet_resource_user_id{}; | ||
| 800 | }; | ||
| 681 | 801 | ||
| 682 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, | 802 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 683 | applet_resource_user_id); | 803 | |
| 804 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 805 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); | ||
| 684 | 806 | ||
| 685 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 807 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 686 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); | 808 | parameters.npad_id, parameters.applet_resource_user_id); |
| 687 | 809 | ||
| 688 | IPC::ResponseBuilder rb{ctx, 2}; | 810 | IPC::ResponseBuilder rb{ctx, 2}; |
| 689 | rb.Push(RESULT_SUCCESS); | 811 | rb.Push(RESULT_SUCCESS); |
| @@ -692,16 +814,22 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx | |||
| 692 | void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | 814 | void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { |
| 693 | // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault | 815 | // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault |
| 694 | IPC::RequestParser rp{ctx}; | 816 | IPC::RequestParser rp{ctx}; |
| 695 | const auto npad_id{rp.Pop<u32>()}; | 817 | struct Parameters { |
| 696 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 818 | u32 npad_id{}; |
| 697 | const auto npad_joy_device_type{rp.Pop<u64>()}; | 819 | INSERT_PADDING_WORDS(1); |
| 820 | u64 applet_resource_user_id{}; | ||
| 821 | u64 npad_joy_device_type{}; | ||
| 822 | }; | ||
| 823 | |||
| 824 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 825 | |||
| 826 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 827 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); | ||
| 698 | 828 | ||
| 699 | LOG_WARNING(Service_HID, | 829 | LOG_WARNING(Service_HID, |
| 700 | "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", | 830 | "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", |
| 701 | npad_id, applet_resource_user_id, npad_joy_device_type); | 831 | parameters.npad_id, parameters.applet_resource_user_id, |
| 702 | 832 | parameters.npad_joy_device_type); | |
| 703 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 704 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); | ||
| 705 | 833 | ||
| 706 | IPC::ResponseBuilder rb{ctx, 2}; | 834 | IPC::ResponseBuilder rb{ctx, 2}; |
| 707 | rb.Push(RESULT_SUCCESS); | 835 | rb.Push(RESULT_SUCCESS); |
| @@ -709,14 +837,19 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | |||
| 709 | 837 | ||
| 710 | void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { | 838 | void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { |
| 711 | IPC::RequestParser rp{ctx}; | 839 | IPC::RequestParser rp{ctx}; |
| 712 | const auto npad_id{rp.Pop<u32>()}; | 840 | struct Parameters { |
| 713 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 841 | u32 npad_id{}; |
| 842 | INSERT_PADDING_WORDS(1); | ||
| 843 | u64 applet_resource_user_id{}; | ||
| 844 | }; | ||
| 845 | |||
| 846 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 714 | 847 | ||
| 715 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, | 848 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 716 | applet_resource_user_id); | 849 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); |
| 717 | 850 | ||
| 718 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 851 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 719 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); | 852 | parameters.npad_id, parameters.applet_resource_user_id); |
| 720 | 853 | ||
| 721 | IPC::ResponseBuilder rb{ctx, 2}; | 854 | IPC::ResponseBuilder rb{ctx, 2}; |
| 722 | rb.Push(RESULT_SUCCESS); | 855 | rb.Push(RESULT_SUCCESS); |
| @@ -728,12 +861,12 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | |||
| 728 | const auto npad_id_2{rp.Pop<u32>()}; | 861 | const auto npad_id_2{rp.Pop<u32>()}; |
| 729 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 862 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 730 | 863 | ||
| 864 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 865 | .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||
| 866 | |||
| 731 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | 867 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", |
| 732 | npad_id_1, npad_id_2, applet_resource_user_id); | 868 | npad_id_1, npad_id_2, applet_resource_user_id); |
| 733 | 869 | ||
| 734 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 735 | controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||
| 736 | |||
| 737 | IPC::ResponseBuilder rb{ctx, 2}; | 870 | IPC::ResponseBuilder rb{ctx, 2}; |
| 738 | rb.Push(RESULT_SUCCESS); | 871 | rb.Push(RESULT_SUCCESS); |
| 739 | } | 872 | } |
| @@ -742,9 +875,9 @@ void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 742 | IPC::RequestParser rp{ctx}; | 875 | IPC::RequestParser rp{ctx}; |
| 743 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 876 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 744 | 877 | ||
| 878 | applet_resource->GetController<Controller_NPad>(HidController::NPad).StartLRAssignmentMode(); | ||
| 879 | |||
| 745 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 880 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 746 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 747 | controller.StartLRAssignmentMode(); | ||
| 748 | 881 | ||
| 749 | IPC::ResponseBuilder rb{ctx, 2}; | 882 | IPC::ResponseBuilder rb{ctx, 2}; |
| 750 | rb.Push(RESULT_SUCCESS); | 883 | rb.Push(RESULT_SUCCESS); |
| @@ -754,9 +887,9 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 754 | IPC::RequestParser rp{ctx}; | 887 | IPC::RequestParser rp{ctx}; |
| 755 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 888 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 756 | 889 | ||
| 890 | applet_resource->GetController<Controller_NPad>(HidController::NPad).StopLRAssignmentMode(); | ||
| 891 | |||
| 757 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 892 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 758 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 759 | controller.StopLRAssignmentMode(); | ||
| 760 | 893 | ||
| 761 | IPC::ResponseBuilder rb{ctx, 2}; | 894 | IPC::ResponseBuilder rb{ctx, 2}; |
| 762 | rb.Push(RESULT_SUCCESS); | 895 | rb.Push(RESULT_SUCCESS); |
| @@ -765,13 +898,13 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 765 | void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { | 898 | void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { |
| 766 | IPC::RequestParser rp{ctx}; | 899 | IPC::RequestParser rp{ctx}; |
| 767 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 900 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 768 | const auto mode{rp.Pop<u64>()}; | 901 | const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()}; |
| 769 | |||
| 770 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id, | ||
| 771 | mode); | ||
| 772 | 902 | ||
| 773 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 903 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 774 | .SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode}); | 904 | .SetNpadHandheldActivationMode(activation_mode); |
| 905 | |||
| 906 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}", | ||
| 907 | applet_resource_user_id, activation_mode); | ||
| 775 | 908 | ||
| 776 | IPC::ResponseBuilder rb{ctx, 2}; | 909 | IPC::ResponseBuilder rb{ctx, 2}; |
| 777 | rb.Push(RESULT_SUCCESS); | 910 | rb.Push(RESULT_SUCCESS); |
| @@ -785,23 +918,24 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { | |||
| 785 | 918 | ||
| 786 | IPC::ResponseBuilder rb{ctx, 4}; | 919 | IPC::ResponseBuilder rb{ctx, 4}; |
| 787 | rb.Push(RESULT_SUCCESS); | 920 | rb.Push(RESULT_SUCCESS); |
| 788 | rb.Push<u64>( | 921 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 789 | static_cast<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 922 | .GetNpadHandheldActivationMode()); |
| 790 | .GetNpadHandheldActivationMode())); | ||
| 791 | } | 923 | } |
| 792 | 924 | ||
| 793 | void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { | 925 | void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { |
| 794 | IPC::RequestParser rp{ctx}; | 926 | IPC::RequestParser rp{ctx}; |
| 795 | const auto npad_1{rp.Pop<u32>()}; | 927 | const auto npad_id_1{rp.Pop<u32>()}; |
| 796 | const auto npad_2{rp.Pop<u32>()}; | 928 | const auto npad_id_2{rp.Pop<u32>()}; |
| 797 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 929 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 798 | 930 | ||
| 799 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", | 931 | const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 800 | applet_resource_user_id, npad_1, npad_2); | 932 | .SwapNpadAssignment(npad_id_1, npad_id_2); |
| 933 | |||
| 934 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | ||
| 935 | npad_id_1, npad_id_2, applet_resource_user_id); | ||
| 801 | 936 | ||
| 802 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 803 | IPC::ResponseBuilder rb{ctx, 2}; | 937 | IPC::ResponseBuilder rb{ctx, 2}; |
| 804 | if (controller.SwapNpadAssignment(npad_1, npad_2)) { | 938 | if (res) { |
| 805 | rb.Push(RESULT_SUCCESS); | 939 | rb.Push(RESULT_SUCCESS); |
| 806 | } else { | 940 | } else { |
| 807 | LOG_ERROR(Service_HID, "Npads are not connected!"); | 941 | LOG_ERROR(Service_HID, "Npads are not connected!"); |
| @@ -811,144 +945,219 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { | |||
| 811 | 945 | ||
| 812 | void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { | 946 | void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { |
| 813 | IPC::RequestParser rp{ctx}; | 947 | IPC::RequestParser rp{ctx}; |
| 814 | const auto npad_id{rp.Pop<u32>()}; | 948 | struct Parameters { |
| 815 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 949 | u32 npad_id{}; |
| 950 | INSERT_PADDING_WORDS(1); | ||
| 951 | u64 applet_resource_user_id{}; | ||
| 952 | }; | ||
| 816 | 953 | ||
| 817 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, | 954 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 818 | applet_resource_user_id); | ||
| 819 | 955 | ||
| 820 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 956 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 957 | parameters.npad_id, parameters.applet_resource_user_id); | ||
| 821 | 958 | ||
| 822 | IPC::ResponseBuilder rb{ctx, 3}; | 959 | IPC::ResponseBuilder rb{ctx, 3}; |
| 823 | rb.Push(RESULT_SUCCESS); | 960 | rb.Push(RESULT_SUCCESS); |
| 824 | rb.Push<bool>(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id)); | 961 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 962 | .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id)); | ||
| 825 | } | 963 | } |
| 826 | 964 | ||
| 827 | void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { | 965 | void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { |
| 828 | IPC::RequestParser rp{ctx}; | 966 | IPC::RequestParser rp{ctx}; |
| 829 | const auto unintended_home_button_input_protection{rp.Pop<bool>()}; | 967 | struct Parameters { |
| 830 | const auto npad_id{rp.Pop<u32>()}; | 968 | bool unintended_home_button_input_protection{}; |
| 831 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 969 | INSERT_PADDING_BYTES(3); |
| 970 | u32 npad_id{}; | ||
| 971 | u64 applet_resource_user_id{}; | ||
| 972 | }; | ||
| 973 | |||
| 974 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 975 | |||
| 976 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 977 | .SetUnintendedHomeButtonInputProtectionEnabled( | ||
| 978 | parameters.unintended_home_button_input_protection, parameters.npad_id); | ||
| 832 | 979 | ||
| 833 | LOG_WARNING(Service_HID, | 980 | LOG_WARNING(Service_HID, |
| 834 | "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," | 981 | "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," |
| 835 | "applet_resource_user_id={}", | 982 | "applet_resource_user_id={}", |
| 836 | npad_id, unintended_home_button_input_protection, applet_resource_user_id); | 983 | parameters.unintended_home_button_input_protection, parameters.npad_id, |
| 837 | 984 | parameters.applet_resource_user_id); | |
| 838 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 839 | controller.SetUnintendedHomeButtonInputProtectionEnabled( | ||
| 840 | unintended_home_button_input_protection, npad_id); | ||
| 841 | 985 | ||
| 842 | IPC::ResponseBuilder rb{ctx, 2}; | 986 | IPC::ResponseBuilder rb{ctx, 2}; |
| 843 | rb.Push(RESULT_SUCCESS); | 987 | rb.Push(RESULT_SUCCESS); |
| 844 | } | 988 | } |
| 845 | 989 | ||
| 846 | void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { | 990 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { |
| 847 | IPC::RequestParser rp{ctx}; | 991 | IPC::RequestParser rp{ctx}; |
| 848 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 992 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
| 993 | |||
| 994 | VibrationDeviceInfo vibration_device_info; | ||
| 995 | |||
| 996 | vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; | ||
| 997 | |||
| 998 | switch (vibration_device_handle.device_index) { | ||
| 999 | case Controller_NPad::DeviceIndex::Left: | ||
| 1000 | vibration_device_info.position = VibrationDevicePosition::Left; | ||
| 1001 | break; | ||
| 1002 | case Controller_NPad::DeviceIndex::Right: | ||
| 1003 | vibration_device_info.position = VibrationDevicePosition::Right; | ||
| 1004 | break; | ||
| 1005 | case Controller_NPad::DeviceIndex::None: | ||
| 1006 | default: | ||
| 1007 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | ||
| 1008 | vibration_device_info.position = VibrationDevicePosition::None; | ||
| 1009 | break; | ||
| 1010 | } | ||
| 849 | 1011 | ||
| 850 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1012 | LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", |
| 1013 | vibration_device_info.type, vibration_device_info.position); | ||
| 1014 | |||
| 1015 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1016 | rb.Push(RESULT_SUCCESS); | ||
| 1017 | rb.PushRaw(vibration_device_info); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | ||
| 1021 | IPC::RequestParser rp{ctx}; | ||
| 1022 | struct Parameters { | ||
| 1023 | Controller_NPad::DeviceHandle vibration_device_handle{}; | ||
| 1024 | Controller_NPad::VibrationValue vibration_value{}; | ||
| 1025 | INSERT_PADDING_WORDS(1); | ||
| 1026 | u64 applet_resource_user_id{}; | ||
| 1027 | }; | ||
| 1028 | |||
| 1029 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1030 | |||
| 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1032 | .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); | ||
| 1033 | |||
| 1034 | LOG_DEBUG(Service_HID, | ||
| 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1036 | parameters.vibration_device_handle.npad_type, | ||
| 1037 | parameters.vibration_device_handle.npad_id, | ||
| 1038 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | ||
| 851 | 1039 | ||
| 852 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(true); | ||
| 853 | IPC::ResponseBuilder rb{ctx, 2}; | 1040 | IPC::ResponseBuilder rb{ctx, 2}; |
| 854 | rb.Push(RESULT_SUCCESS); | 1041 | rb.Push(RESULT_SUCCESS); |
| 855 | } | 1042 | } |
| 856 | 1043 | ||
| 857 | void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { | 1044 | void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { |
| 1045 | IPC::RequestParser rp{ctx}; | ||
| 1046 | struct Parameters { | ||
| 1047 | Controller_NPad::DeviceHandle vibration_device_handle{}; | ||
| 1048 | INSERT_PADDING_WORDS(1); | ||
| 1049 | u64 applet_resource_user_id{}; | ||
| 1050 | }; | ||
| 1051 | |||
| 1052 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1053 | |||
| 1054 | LOG_DEBUG(Service_HID, | ||
| 1055 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1056 | parameters.vibration_device_handle.npad_type, | ||
| 1057 | parameters.vibration_device_handle.npad_id, | ||
| 1058 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | ||
| 1059 | |||
| 1060 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1061 | rb.Push(RESULT_SUCCESS); | ||
| 1062 | rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1063 | .GetLastVibration(parameters.vibration_device_handle)); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | ||
| 858 | LOG_DEBUG(Service_HID, "called"); | 1067 | LOG_DEBUG(Service_HID, "called"); |
| 859 | 1068 | ||
| 860 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(false); | 1069 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 861 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 862 | rb.Push(RESULT_SUCCESS); | 1070 | rb.Push(RESULT_SUCCESS); |
| 1071 | rb.PushIpcInterface<IActiveVibrationDeviceList>(applet_resource); | ||
| 863 | } | 1072 | } |
| 864 | 1073 | ||
| 865 | void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | 1074 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { |
| 866 | IPC::RequestParser rp{ctx}; | 1075 | IPC::RequestParser rp{ctx}; |
| 867 | const auto controller{rp.Pop<u32>()}; | 1076 | const auto can_vibrate{rp.Pop<bool>()}; |
| 868 | const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; | ||
| 869 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 870 | 1077 | ||
| 871 | LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, | 1078 | Settings::values.vibration_enabled.SetValue(can_vibrate); |
| 872 | applet_resource_user_id); | 1079 | |
| 1080 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | ||
| 873 | 1081 | ||
| 874 | IPC::ResponseBuilder rb{ctx, 2}; | 1082 | IPC::ResponseBuilder rb{ctx, 2}; |
| 875 | rb.Push(RESULT_SUCCESS); | 1083 | rb.Push(RESULT_SUCCESS); |
| 1084 | } | ||
| 876 | 1085 | ||
| 877 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1086 | void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { |
| 878 | .VibrateController({controller}, {vibration_values}); | 1087 | LOG_DEBUG(Service_HID, "called"); |
| 1088 | |||
| 1089 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1090 | rb.Push(RESULT_SUCCESS); | ||
| 1091 | rb.Push(Settings::values.vibration_enabled.GetValue()); | ||
| 879 | } | 1092 | } |
| 880 | 1093 | ||
| 881 | void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { | 1094 | void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { |
| 882 | IPC::RequestParser rp{ctx}; | 1095 | IPC::RequestParser rp{ctx}; |
| 883 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1096 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 884 | 1097 | ||
| 885 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1098 | const auto handles = ctx.ReadBuffer(0); |
| 886 | |||
| 887 | const auto controllers = ctx.ReadBuffer(0); | ||
| 888 | const auto vibrations = ctx.ReadBuffer(1); | 1099 | const auto vibrations = ctx.ReadBuffer(1); |
| 889 | 1100 | ||
| 890 | std::vector<u32> controller_list(controllers.size() / sizeof(u32)); | 1101 | std::vector<Controller_NPad::DeviceHandle> vibration_device_handles( |
| 891 | std::vector<Controller_NPad::Vibration> vibration_list(vibrations.size() / | 1102 | handles.size() / sizeof(Controller_NPad::DeviceHandle)); |
| 892 | sizeof(Controller_NPad::Vibration)); | 1103 | std::vector<Controller_NPad::VibrationValue> vibration_values( |
| 1104 | vibrations.size() / sizeof(Controller_NPad::VibrationValue)); | ||
| 893 | 1105 | ||
| 894 | std::memcpy(controller_list.data(), controllers.data(), controllers.size()); | 1106 | std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); |
| 895 | std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); | 1107 | std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); |
| 896 | 1108 | ||
| 897 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1109 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 898 | .VibrateController(controller_list, vibration_list); | 1110 | .VibrateControllers(vibration_device_handles, vibration_values); |
| 1111 | |||
| 1112 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 899 | 1113 | ||
| 900 | IPC::ResponseBuilder rb{ctx, 2}; | 1114 | IPC::ResponseBuilder rb{ctx, 2}; |
| 901 | rb.Push(RESULT_SUCCESS); | 1115 | rb.Push(RESULT_SUCCESS); |
| 902 | } | 1116 | } |
| 903 | 1117 | ||
| 904 | void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { | 1118 | void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { |
| 905 | IPC::RequestParser rp{ctx}; | 1119 | IPC::RequestParser rp{ctx}; |
| 906 | const auto controller_id{rp.Pop<u32>()}; | ||
| 907 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1120 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 908 | 1121 | ||
| 909 | LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, | 1122 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 910 | applet_resource_user_id); | 1123 | .SetPermitVibrationSession(true); |
| 911 | |||
| 912 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 913 | rb.Push(RESULT_SUCCESS); | ||
| 914 | rb.PushRaw<Controller_NPad::Vibration>( | ||
| 915 | applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); | ||
| 916 | } | ||
| 917 | 1124 | ||
| 918 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { | 1125 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 919 | LOG_DEBUG(Service_HID, "called"); | ||
| 920 | 1126 | ||
| 921 | IPC::ResponseBuilder rb{ctx, 4}; | 1127 | IPC::ResponseBuilder rb{ctx, 2}; |
| 922 | rb.Push(RESULT_SUCCESS); | 1128 | rb.Push(RESULT_SUCCESS); |
| 923 | rb.Push<u32>(1); | ||
| 924 | rb.Push<u32>(0); | ||
| 925 | } | 1129 | } |
| 926 | 1130 | ||
| 927 | void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | 1131 | void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { |
| 1132 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1133 | .SetPermitVibrationSession(false); | ||
| 1134 | |||
| 928 | LOG_DEBUG(Service_HID, "called"); | 1135 | LOG_DEBUG(Service_HID, "called"); |
| 929 | 1136 | ||
| 930 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1137 | IPC::ResponseBuilder rb{ctx, 2}; |
| 931 | rb.Push(RESULT_SUCCESS); | 1138 | rb.Push(RESULT_SUCCESS); |
| 932 | rb.PushIpcInterface<IActiveVibrationDeviceList>(); | ||
| 933 | } | 1139 | } |
| 934 | 1140 | ||
| 935 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | 1141 | void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { |
| 936 | IPC::RequestParser rp{ctx}; | 1142 | IPC::RequestParser rp{ctx}; |
| 937 | const auto can_vibrate{rp.Pop<bool>()}; | 1143 | struct Parameters { |
| 938 | Settings::values.vibration_enabled = can_vibrate; | 1144 | Controller_NPad::DeviceHandle vibration_device_handle{}; |
| 1145 | INSERT_PADDING_WORDS(1); | ||
| 1146 | u64 applet_resource_user_id{}; | ||
| 1147 | }; | ||
| 939 | 1148 | ||
| 940 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 1149 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 941 | 1150 | ||
| 942 | IPC::ResponseBuilder rb{ctx, 2}; | 1151 | LOG_DEBUG(Service_HID, |
| 943 | rb.Push(RESULT_SUCCESS); | 1152 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 944 | } | 1153 | parameters.vibration_device_handle.npad_type, |
| 945 | 1154 | parameters.vibration_device_handle.npad_id, | |
| 946 | void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | 1155 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 947 | LOG_DEBUG(Service_HID, "called"); | ||
| 948 | 1156 | ||
| 949 | IPC::ResponseBuilder rb{ctx, 3}; | 1157 | IPC::ResponseBuilder rb{ctx, 3}; |
| 950 | rb.Push(RESULT_SUCCESS); | 1158 | rb.Push(RESULT_SUCCESS); |
| 951 | rb.Push(Settings::values.vibration_enabled); | 1159 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 1160 | .IsVibrationDeviceMounted(parameters.vibration_device_handle)); | ||
| 952 | } | 1161 | } |
| 953 | 1162 | ||
| 954 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1163 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| @@ -964,11 +1173,19 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 964 | 1173 | ||
| 965 | void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1174 | void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 966 | IPC::RequestParser rp{ctx}; | 1175 | IPC::RequestParser rp{ctx}; |
| 967 | const auto handle{rp.Pop<u32>()}; | 1176 | struct Parameters { |
| 968 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1177 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 1178 | INSERT_PADDING_WORDS(1); | ||
| 1179 | u64 applet_resource_user_id{}; | ||
| 1180 | }; | ||
| 969 | 1181 | ||
| 970 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 1182 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 971 | applet_resource_user_id); | 1183 | |
| 1184 | LOG_WARNING( | ||
| 1185 | Service_HID, | ||
| 1186 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1187 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 1188 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 972 | 1189 | ||
| 973 | IPC::ResponseBuilder rb{ctx, 2}; | 1190 | IPC::ResponseBuilder rb{ctx, 2}; |
| 974 | rb.Push(RESULT_SUCCESS); | 1191 | rb.Push(RESULT_SUCCESS); |
| @@ -976,11 +1193,19 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 976 | 1193 | ||
| 977 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1194 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 978 | IPC::RequestParser rp{ctx}; | 1195 | IPC::RequestParser rp{ctx}; |
| 979 | const auto handle{rp.Pop<u32>()}; | 1196 | struct Parameters { |
| 980 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1197 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 1198 | INSERT_PADDING_WORDS(1); | ||
| 1199 | u64 applet_resource_user_id{}; | ||
| 1200 | }; | ||
| 981 | 1201 | ||
| 982 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 1202 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 983 | applet_resource_user_id); | 1203 | |
| 1204 | LOG_WARNING( | ||
| 1205 | Service_HID, | ||
| 1206 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1207 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 1208 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 984 | 1209 | ||
| 985 | IPC::ResponseBuilder rb{ctx, 2}; | 1210 | IPC::ResponseBuilder rb{ctx, 2}; |
| 986 | rb.Push(RESULT_SUCCESS); | 1211 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index fd0372b18..c8e4a4b55 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -86,17 +86,15 @@ public: | |||
| 86 | 86 | ||
| 87 | private: | 87 | private: |
| 88 | void CreateAppletResource(Kernel::HLERequestContext& ctx); | 88 | void CreateAppletResource(Kernel::HLERequestContext& ctx); |
| 89 | void ActivateXpad(Kernel::HLERequestContext& ctx); | ||
| 90 | void GetXpadIDs(Kernel::HLERequestContext& ctx); | ||
| 91 | void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 92 | void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 93 | void ActivateDebugPad(Kernel::HLERequestContext& ctx); | 89 | void ActivateDebugPad(Kernel::HLERequestContext& ctx); |
| 94 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); | 90 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); |
| 95 | void ActivateMouse(Kernel::HLERequestContext& ctx); | 91 | void ActivateMouse(Kernel::HLERequestContext& ctx); |
| 96 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); | 92 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); |
| 97 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | 93 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); |
| 98 | void ActivateGesture(Kernel::HLERequestContext& ctx); | 94 | void ActivateXpad(Kernel::HLERequestContext& ctx); |
| 99 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | 95 | void GetXpadIDs(Kernel::HLERequestContext& ctx); |
| 96 | void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 97 | void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 100 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); | 98 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 101 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | 99 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 102 | void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); | 100 | void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); |
| @@ -104,6 +102,7 @@ private: | |||
| 104 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 102 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 105 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 103 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 106 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); | 104 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); |
| 105 | void ActivateGesture(Kernel::HLERequestContext& ctx); | ||
| 107 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 106 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| 108 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 107 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| 109 | void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); | 108 | void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); |
| @@ -112,6 +111,7 @@ private: | |||
| 112 | void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); | 111 | void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); |
| 113 | void DisconnectNpad(Kernel::HLERequestContext& ctx); | 112 | void DisconnectNpad(Kernel::HLERequestContext& ctx); |
| 114 | void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); | 113 | void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); |
| 114 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | ||
| 115 | void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); | 115 | void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); |
| 116 | void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); | 116 | void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); |
| 117 | void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); | 117 | void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); |
| @@ -125,15 +125,16 @@ private: | |||
| 125 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); | 125 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); |
| 126 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); | 126 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); |
| 127 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); | 127 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); |
| 128 | void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); | 128 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); |
| 129 | void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 130 | void SendVibrationValue(Kernel::HLERequestContext& ctx); | 129 | void SendVibrationValue(Kernel::HLERequestContext& ctx); |
| 131 | void SendVibrationValues(Kernel::HLERequestContext& ctx); | ||
| 132 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); | 130 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); |
| 133 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); | ||
| 134 | void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); | 131 | void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); |
| 135 | void PermitVibration(Kernel::HLERequestContext& ctx); | 132 | void PermitVibration(Kernel::HLERequestContext& ctx); |
| 136 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); | 133 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); |
| 134 | void SendVibrationValues(Kernel::HLERequestContext& ctx); | ||
| 135 | void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 136 | void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 137 | void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); | ||
| 137 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 138 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 138 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 139 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 139 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 140 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| @@ -146,6 +147,22 @@ private: | |||
| 146 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | 147 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); |
| 147 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | 148 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); |
| 148 | 149 | ||
| 150 | enum class VibrationDeviceType : u32 { | ||
| 151 | LinearResonantActuator = 1, | ||
| 152 | }; | ||
| 153 | |||
| 154 | enum class VibrationDevicePosition : u32 { | ||
| 155 | None = 0, | ||
| 156 | Left = 1, | ||
| 157 | Right = 2, | ||
| 158 | }; | ||
| 159 | |||
| 160 | struct VibrationDeviceInfo { | ||
| 161 | VibrationDeviceType type{}; | ||
| 162 | VibrationDevicePosition position{}; | ||
| 163 | }; | ||
| 164 | static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); | ||
| 165 | |||
| 149 | std::shared_ptr<IAppletResource> applet_resource; | 166 | std::shared_ptr<IAppletResource> applet_resource; |
| 150 | Core::System& system; | 167 | Core::System& system; |
| 151 | }; | 168 | }; |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 58ee1f712..2594e6839 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | 7 | #include "core/file_sys/control_metadata.h" |
| 7 | #include "core/file_sys/patch_manager.h" | 8 | #include "core/file_sys/patch_manager.h" |
| 8 | #include "core/file_sys/vfs.h" | 9 | #include "core/file_sys/vfs.h" |
| @@ -29,8 +30,8 @@ IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountPro | |||
| 29 | 30 | ||
| 30 | IAccountProxyInterface::~IAccountProxyInterface() = default; | 31 | IAccountProxyInterface::~IAccountProxyInterface() = default; |
| 31 | 32 | ||
| 32 | IApplicationManagerInterface::IApplicationManagerInterface() | 33 | IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) |
| 33 | : ServiceFramework{"IApplicationManagerInterface"} { | 34 | : ServiceFramework{"IApplicationManagerInterface"}, system{system_} { |
| 34 | // clang-format off | 35 | // clang-format off |
| 35 | static const FunctionInfo functions[] = { | 36 | static const FunctionInfo functions[] = { |
| 36 | {0, nullptr, "ListApplicationRecord"}, | 37 | {0, nullptr, "ListApplicationRecord"}, |
| @@ -298,7 +299,8 @@ void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestC | |||
| 298 | 299 | ||
| 299 | const auto size = ctx.GetWriteBufferSize(); | 300 | const auto size = ctx.GetWriteBufferSize(); |
| 300 | 301 | ||
| 301 | const FileSys::PatchManager pm{title_id}; | 302 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 303 | system.GetContentProvider()}; | ||
| 302 | const auto control = pm.GetControlMetadata(); | 304 | const auto control = pm.GetControlMetadata(); |
| 303 | 305 | ||
| 304 | std::vector<u8> out; | 306 | std::vector<u8> out; |
| @@ -538,14 +540,14 @@ IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface() | |||
| 538 | 540 | ||
| 539 | IFactoryResetInterface::~IFactoryResetInterface() = default; | 541 | IFactoryResetInterface::~IFactoryResetInterface() = default; |
| 540 | 542 | ||
| 541 | NS::NS(const char* name) : ServiceFramework{name} { | 543 | NS::NS(const char* name, Core::System& system_) : ServiceFramework{name}, system{system_} { |
| 542 | // clang-format off | 544 | // clang-format off |
| 543 | static const FunctionInfo functions[] = { | 545 | static const FunctionInfo functions[] = { |
| 544 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, | 546 | {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, |
| 545 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, | 547 | {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, |
| 546 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, | 548 | {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, |
| 547 | {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, | 549 | {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, |
| 548 | {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, | 550 | {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"}, |
| 549 | {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, | 551 | {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, |
| 550 | {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, | 552 | {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, |
| 551 | {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, | 553 | {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, |
| @@ -558,7 +560,7 @@ NS::NS(const char* name) : ServiceFramework{name} { | |||
| 558 | NS::~NS() = default; | 560 | NS::~NS() = default; |
| 559 | 561 | ||
| 560 | std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { | 562 | std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { |
| 561 | return GetInterface<IApplicationManagerInterface>(); | 563 | return GetInterface<IApplicationManagerInterface>(system); |
| 562 | } | 564 | } |
| 563 | 565 | ||
| 564 | class NS_DEV final : public ServiceFramework<NS_DEV> { | 566 | class NS_DEV final : public ServiceFramework<NS_DEV> { |
| @@ -678,11 +680,11 @@ public: | |||
| 678 | 680 | ||
| 679 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { | 681 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { |
| 680 | 682 | ||
| 681 | std::make_shared<NS>("ns:am2")->InstallAsService(service_manager); | 683 | std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager); |
| 682 | std::make_shared<NS>("ns:ec")->InstallAsService(service_manager); | 684 | std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager); |
| 683 | std::make_shared<NS>("ns:rid")->InstallAsService(service_manager); | 685 | std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); |
| 684 | std::make_shared<NS>("ns:rt")->InstallAsService(service_manager); | 686 | std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); |
| 685 | std::make_shared<NS>("ns:web")->InstallAsService(service_manager); | 687 | std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); |
| 686 | 688 | ||
| 687 | std::make_shared<NS_DEV>()->InstallAsService(service_manager); | 689 | std::make_shared<NS_DEV>()->InstallAsService(service_manager); |
| 688 | std::make_shared<NS_SU>()->InstallAsService(service_manager); | 690 | std::make_shared<NS_SU>()->InstallAsService(service_manager); |
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index c2554b878..c90ccd755 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | 8 | ||
| 9 | namespace Core { | ||
| 10 | class System; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Service { | 13 | namespace Service { |
| 10 | 14 | ||
| 11 | namespace FileSystem { | 15 | namespace FileSystem { |
| @@ -22,7 +26,7 @@ public: | |||
| 22 | 26 | ||
| 23 | class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { | 27 | class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { |
| 24 | public: | 28 | public: |
| 25 | explicit IApplicationManagerInterface(); | 29 | explicit IApplicationManagerInterface(Core::System& system_); |
| 26 | ~IApplicationManagerInterface() override; | 30 | ~IApplicationManagerInterface() override; |
| 27 | 31 | ||
| 28 | ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); | 32 | ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); |
| @@ -32,6 +36,8 @@ private: | |||
| 32 | void GetApplicationControlData(Kernel::HLERequestContext& ctx); | 36 | void GetApplicationControlData(Kernel::HLERequestContext& ctx); |
| 33 | void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); | 37 | void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); |
| 34 | void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); | 38 | void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); |
| 39 | |||
| 40 | Core::System& system; | ||
| 35 | }; | 41 | }; |
| 36 | 42 | ||
| 37 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { | 43 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { |
| @@ -72,13 +78,13 @@ public: | |||
| 72 | 78 | ||
| 73 | class NS final : public ServiceFramework<NS> { | 79 | class NS final : public ServiceFramework<NS> { |
| 74 | public: | 80 | public: |
| 75 | explicit NS(const char* name); | 81 | explicit NS(const char* name, Core::System& system_); |
| 76 | ~NS() override; | 82 | ~NS() override; |
| 77 | 83 | ||
| 78 | std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; | 84 | std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; |
| 79 | 85 | ||
| 80 | private: | 86 | private: |
| 81 | template <typename T> | 87 | template <typename T, typename... Args> |
| 82 | void PushInterface(Kernel::HLERequestContext& ctx) { | 88 | void PushInterface(Kernel::HLERequestContext& ctx) { |
| 83 | LOG_DEBUG(Service_NS, "called"); | 89 | LOG_DEBUG(Service_NS, "called"); |
| 84 | 90 | ||
| @@ -87,13 +93,23 @@ private: | |||
| 87 | rb.PushIpcInterface<T>(); | 93 | rb.PushIpcInterface<T>(); |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | template <typename T> | 96 | void PushIApplicationManagerInterface(Kernel::HLERequestContext& ctx) { |
| 91 | std::shared_ptr<T> GetInterface() const { | 97 | LOG_DEBUG(Service_NS, "called"); |
| 98 | |||
| 99 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 100 | rb.Push(RESULT_SUCCESS); | ||
| 101 | rb.PushIpcInterface<IApplicationManagerInterface>(system); | ||
| 102 | } | ||
| 103 | |||
| 104 | template <typename T, typename... Args> | ||
| 105 | std::shared_ptr<T> GetInterface(Args&&... args) const { | ||
| 92 | static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, | 106 | static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, |
| 93 | "Not a base of ServiceFrameworkBase"); | 107 | "Not a base of ServiceFrameworkBase"); |
| 94 | 108 | ||
| 95 | return std::make_shared<T>(); | 109 | return std::make_shared<T>(std::forward<Args>(args)...); |
| 96 | } | 110 | } |
| 111 | |||
| 112 | Core::System& system; | ||
| 97 | }; | 113 | }; |
| 98 | 114 | ||
| 99 | /// Registers all NS services with the specified service manager. | 115 | /// Registers all NS services with the specified service manager. |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 0240d6643..5681599ba 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -24,25 +24,37 @@ public: | |||
| 24 | explicit nvdevice(Core::System& system) : system{system} {} | 24 | explicit nvdevice(Core::System& system) : system{system} {} |
| 25 | virtual ~nvdevice() = default; | 25 | virtual ~nvdevice() = default; |
| 26 | 26 | ||
| 27 | union Ioctl { | 27 | /** |
| 28 | u32_le raw; | 28 | * Handles an ioctl1 request. |
| 29 | BitField<0, 8, u32> cmd; | 29 | * @param command The ioctl command id. |
| 30 | BitField<8, 8, u32> group; | 30 | * @param input A buffer containing the input data for the ioctl. |
| 31 | BitField<16, 14, u32> length; | 31 | * @param output A buffer where the output data will be written to. |
| 32 | BitField<30, 1, u32> is_in; | 32 | * @returns The result code of the ioctl. |
| 33 | BitField<31, 1, u32> is_out; | 33 | */ |
| 34 | }; | 34 | virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 35 | std::vector<u8>& output) = 0; | ||
| 36 | |||
| 37 | /** | ||
| 38 | * Handles an ioctl2 request. | ||
| 39 | * @param command The ioctl command id. | ||
| 40 | * @param input A buffer containing the input data for the ioctl. | ||
| 41 | * @param inline_input A buffer containing the input data for the ioctl which has been inlined. | ||
| 42 | * @param output A buffer where the output data will be written to. | ||
| 43 | * @returns The result code of the ioctl. | ||
| 44 | */ | ||
| 45 | virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 46 | const std::vector<u8>& inline_input, std::vector<u8>& output) = 0; | ||
| 35 | 47 | ||
| 36 | /** | 48 | /** |
| 37 | * Handles an ioctl request. | 49 | * Handles an ioctl3 request. |
| 38 | * @param command The ioctl command id. | 50 | * @param command The ioctl command id. |
| 39 | * @param input A buffer containing the input data for the ioctl. | 51 | * @param input A buffer containing the input data for the ioctl. |
| 40 | * @param output A buffer where the output data will be written to. | 52 | * @param output A buffer where the output data will be written to. |
| 53 | * @param inline_output A buffer where the inlined output data will be written to. | ||
| 41 | * @returns The result code of the ioctl. | 54 | * @returns The result code of the ioctl. |
| 42 | */ | 55 | */ |
| 43 | virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 56 | virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, |
| 44 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 57 | std::vector<u8>& inline_output) = 0; |
| 45 | IoctlVersion version) = 0; | ||
| 46 | 58 | ||
| 47 | protected: | 59 | protected: |
| 48 | Core::System& system; | 60 | Core::System& system; |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 3f7b8e670..ce615c758 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -18,11 +18,22 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_de | |||
| 18 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | 18 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} |
| 19 | nvdisp_disp0 ::~nvdisp_disp0() = default; | 19 | nvdisp_disp0 ::~nvdisp_disp0() = default; |
| 20 | 20 | ||
| 21 | u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 21 | NvResult nvdisp_disp0::Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 22 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 22 | std::vector<u8>& output) { |
| 23 | IoctlVersion version) { | 23 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 24 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 24 | return NvResult::NotImplemented; |
| 25 | return 0; | 25 | } |
| 26 | |||
| 27 | NvResult nvdisp_disp0::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 28 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 29 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 30 | return NvResult::NotImplemented; | ||
| 31 | } | ||
| 32 | |||
| 33 | NvResult nvdisp_disp0::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 34 | std::vector<u8>& inline_output) { | ||
| 35 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 36 | return NvResult::NotImplemented; | ||
| 26 | } | 37 | } |
| 27 | 38 | ||
| 28 | void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, | 39 | void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 6fcdeee84..55a33b7e4 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | |||
| @@ -20,9 +20,11 @@ public: | |||
| 20 | explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 20 | explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 21 | ~nvdisp_disp0() override; | 21 | ~nvdisp_disp0() override; |
| 22 | 22 | ||
| 23 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 23 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 24 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 24 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 25 | IoctlVersion version) override; | 25 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 26 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 27 | std::vector<u8>& inline_output) override; | ||
| 26 | 28 | ||
| 27 | /// Performs a screen flip, drawing the buffer pointed to by the handle. | 29 | /// Performs a screen flip, drawing the buffer pointed to by the handle. |
| 28 | void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, | 30 | void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index f2529a12e..6b062e10e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -17,59 +17,77 @@ | |||
| 17 | 17 | ||
| 18 | namespace Service::Nvidia::Devices { | 18 | namespace Service::Nvidia::Devices { |
| 19 | 19 | ||
| 20 | namespace NvErrCodes { | ||
| 21 | constexpr u32 Success{}; | ||
| 22 | constexpr u32 OutOfMemory{static_cast<u32>(-12)}; | ||
| 23 | constexpr u32 InvalidInput{static_cast<u32>(-22)}; | ||
| 24 | } // namespace NvErrCodes | ||
| 25 | |||
| 26 | nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | 20 | nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) |
| 27 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | 21 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} |
| 28 | nvhost_as_gpu::~nvhost_as_gpu() = default; | 22 | nvhost_as_gpu::~nvhost_as_gpu() = default; |
| 29 | 23 | ||
| 30 | u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 24 | NvResult nvhost_as_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 31 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 25 | std::vector<u8>& output) { |
| 32 | IoctlVersion version) { | 26 | switch (command.group) { |
| 33 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 27 | case 'A': |
| 34 | command.raw, input.size(), output.size()); | 28 | switch (command.cmd) { |
| 35 | 29 | case 0x1: | |
| 36 | switch (static_cast<IoctlCommand>(command.raw)) { | 30 | return BindChannel(input, output); |
| 37 | case IoctlCommand::IocInitalizeExCommand: | 31 | case 0x2: |
| 38 | return InitalizeEx(input, output); | 32 | return AllocateSpace(input, output); |
| 39 | case IoctlCommand::IocAllocateSpaceCommand: | 33 | case 0x3: |
| 40 | return AllocateSpace(input, output); | 34 | return FreeSpace(input, output); |
| 41 | case IoctlCommand::IocMapBufferExCommand: | 35 | case 0x5: |
| 42 | return MapBufferEx(input, output); | 36 | return UnmapBuffer(input, output); |
| 43 | case IoctlCommand::IocBindChannelCommand: | 37 | case 0x6: |
| 44 | return BindChannel(input, output); | 38 | return MapBufferEx(input, output); |
| 45 | case IoctlCommand::IocGetVaRegionsCommand: | 39 | case 0x8: |
| 46 | return GetVARegions(input, output); | 40 | return GetVARegions(input, output); |
| 47 | case IoctlCommand::IocUnmapBufferCommand: | 41 | case 0x9: |
| 48 | return UnmapBuffer(input, output); | 42 | return InitalizeEx(input, output); |
| 49 | case IoctlCommand::IocFreeSpaceCommand: | 43 | case 0x14: |
| 50 | return FreeSpace(input, output); | 44 | return Remap(input, output); |
| 45 | default: | ||
| 46 | break; | ||
| 47 | } | ||
| 48 | break; | ||
| 51 | default: | 49 | default: |
| 52 | break; | 50 | break; |
| 53 | } | 51 | } |
| 54 | 52 | ||
| 55 | if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand) { | 53 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 56 | return Remap(input, output); | 54 | return NvResult::NotImplemented; |
| 57 | } | 55 | } |
| 56 | |||
| 57 | NvResult nvhost_as_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 58 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 59 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 60 | return NvResult::NotImplemented; | ||
| 61 | } | ||
| 58 | 62 | ||
| 59 | UNIMPLEMENTED_MSG("Unimplemented ioctl command"); | 63 | NvResult nvhost_as_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, |
| 60 | return 0; | 64 | std::vector<u8>& inline_output) { |
| 65 | switch (command.group) { | ||
| 66 | case 'A': | ||
| 67 | switch (command.cmd) { | ||
| 68 | case 0x8: | ||
| 69 | return GetVARegions(input, output, inline_output); | ||
| 70 | default: | ||
| 71 | break; | ||
| 72 | } | ||
| 73 | break; | ||
| 74 | default: | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 78 | return NvResult::NotImplemented; | ||
| 61 | } | 79 | } |
| 62 | 80 | ||
| 63 | u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { | 81 | NvResult nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { |
| 64 | IoctlInitalizeEx params{}; | 82 | IoctlInitalizeEx params{}; |
| 65 | std::memcpy(¶ms, input.data(), input.size()); | 83 | std::memcpy(¶ms, input.data(), input.size()); |
| 66 | 84 | ||
| 67 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x{:X}", params.big_page_size); | 85 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x{:X}", params.big_page_size); |
| 68 | 86 | ||
| 69 | return 0; | 87 | return NvResult::Success; |
| 70 | } | 88 | } |
| 71 | 89 | ||
| 72 | u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { | 90 | NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { |
| 73 | IoctlAllocSpace params{}; | 91 | IoctlAllocSpace params{}; |
| 74 | std::memcpy(¶ms, input.data(), input.size()); | 92 | std::memcpy(¶ms, input.data(), input.size()); |
| 75 | 93 | ||
| @@ -83,17 +101,17 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& | |||
| 83 | params.offset = system.GPU().MemoryManager().Allocate(size, params.align); | 101 | params.offset = system.GPU().MemoryManager().Allocate(size, params.align); |
| 84 | } | 102 | } |
| 85 | 103 | ||
| 86 | auto result{NvErrCodes::Success}; | 104 | auto result = NvResult::Success; |
| 87 | if (!params.offset) { | 105 | if (!params.offset) { |
| 88 | LOG_CRITICAL(Service_NVDRV, "allocation failed for size {}", size); | 106 | LOG_CRITICAL(Service_NVDRV, "allocation failed for size {}", size); |
| 89 | result = NvErrCodes::OutOfMemory; | 107 | result = NvResult::InsufficientMemory; |
| 90 | } | 108 | } |
| 91 | 109 | ||
| 92 | std::memcpy(output.data(), ¶ms, output.size()); | 110 | std::memcpy(output.data(), ¶ms, output.size()); |
| 93 | return result; | 111 | return result; |
| 94 | } | 112 | } |
| 95 | 113 | ||
| 96 | u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { | 114 | NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { |
| 97 | IoctlFreeSpace params{}; | 115 | IoctlFreeSpace params{}; |
| 98 | std::memcpy(¶ms, input.data(), input.size()); | 116 | std::memcpy(¶ms, input.data(), input.size()); |
| 99 | 117 | ||
| @@ -104,15 +122,15 @@ u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& outp | |||
| 104 | static_cast<std::size_t>(params.pages) * params.page_size); | 122 | static_cast<std::size_t>(params.pages) * params.page_size); |
| 105 | 123 | ||
| 106 | std::memcpy(output.data(), ¶ms, output.size()); | 124 | std::memcpy(output.data(), ¶ms, output.size()); |
| 107 | return NvErrCodes::Success; | 125 | return NvResult::Success; |
| 108 | } | 126 | } |
| 109 | 127 | ||
| 110 | u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { | 128 | NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { |
| 111 | const auto num_entries = input.size() / sizeof(IoctlRemapEntry); | 129 | const auto num_entries = input.size() / sizeof(IoctlRemapEntry); |
| 112 | 130 | ||
| 113 | LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); | 131 | LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); |
| 114 | 132 | ||
| 115 | auto result{NvErrCodes::Success}; | 133 | auto result = NvResult::Success; |
| 116 | std::vector<IoctlRemapEntry> entries(num_entries); | 134 | std::vector<IoctlRemapEntry> entries(num_entries); |
| 117 | std::memcpy(entries.data(), input.data(), input.size()); | 135 | std::memcpy(entries.data(), input.data(), input.size()); |
| 118 | 136 | ||
| @@ -123,7 +141,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) | |||
| 123 | const auto object{nvmap_dev->GetObject(entry.nvmap_handle)}; | 141 | const auto object{nvmap_dev->GetObject(entry.nvmap_handle)}; |
| 124 | if (!object) { | 142 | if (!object) { |
| 125 | LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", entry.nvmap_handle); | 143 | LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", entry.nvmap_handle); |
| 126 | result = NvErrCodes::InvalidInput; | 144 | result = NvResult::InvalidState; |
| 127 | break; | 145 | break; |
| 128 | } | 146 | } |
| 129 | 147 | ||
| @@ -134,7 +152,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) | |||
| 134 | 152 | ||
| 135 | if (!addr) { | 153 | if (!addr) { |
| 136 | LOG_CRITICAL(Service_NVDRV, "map returned an invalid address!"); | 154 | LOG_CRITICAL(Service_NVDRV, "map returned an invalid address!"); |
| 137 | result = NvErrCodes::InvalidInput; | 155 | result = NvResult::InvalidState; |
| 138 | break; | 156 | break; |
| 139 | } | 157 | } |
| 140 | } | 158 | } |
| @@ -143,7 +161,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) | |||
| 143 | return result; | 161 | return result; |
| 144 | } | 162 | } |
| 145 | 163 | ||
| 146 | u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | 164 | NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { |
| 147 | IoctlMapBufferEx params{}; | 165 | IoctlMapBufferEx params{}; |
| 148 | std::memcpy(¶ms, input.data(), input.size()); | 166 | std::memcpy(¶ms, input.data(), input.size()); |
| 149 | 167 | ||
| @@ -157,7 +175,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 157 | if (!object) { | 175 | if (!object) { |
| 158 | LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", params.nvmap_handle); | 176 | LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", params.nvmap_handle); |
| 159 | std::memcpy(output.data(), ¶ms, output.size()); | 177 | std::memcpy(output.data(), ¶ms, output.size()); |
| 160 | return NvErrCodes::InvalidInput; | 178 | return NvResult::InvalidState; |
| 161 | } | 179 | } |
| 162 | 180 | ||
| 163 | // The real nvservices doesn't make a distinction between handles and ids, and | 181 | // The real nvservices doesn't make a distinction between handles and ids, and |
| @@ -184,16 +202,16 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 184 | params.mapping_size, params.offset); | 202 | params.mapping_size, params.offset); |
| 185 | 203 | ||
| 186 | std::memcpy(output.data(), ¶ms, output.size()); | 204 | std::memcpy(output.data(), ¶ms, output.size()); |
| 187 | return NvErrCodes::InvalidInput; | 205 | return NvResult::InvalidState; |
| 188 | } | 206 | } |
| 189 | 207 | ||
| 190 | std::memcpy(output.data(), ¶ms, output.size()); | 208 | std::memcpy(output.data(), ¶ms, output.size()); |
| 191 | return NvErrCodes::Success; | 209 | return NvResult::Success; |
| 192 | } else { | 210 | } else { |
| 193 | LOG_CRITICAL(Service_NVDRV, "address not mapped offset={}", params.offset); | 211 | LOG_CRITICAL(Service_NVDRV, "address not mapped offset={}", params.offset); |
| 194 | 212 | ||
| 195 | std::memcpy(output.data(), ¶ms, output.size()); | 213 | std::memcpy(output.data(), ¶ms, output.size()); |
| 196 | return NvErrCodes::InvalidInput; | 214 | return NvResult::InvalidState; |
| 197 | } | 215 | } |
| 198 | } | 216 | } |
| 199 | 217 | ||
| @@ -213,10 +231,10 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 213 | params.offset = gpu.MemoryManager().Map(physical_address, params.offset, size); | 231 | params.offset = gpu.MemoryManager().Map(physical_address, params.offset, size); |
| 214 | } | 232 | } |
| 215 | 233 | ||
| 216 | auto result{NvErrCodes::Success}; | 234 | auto result = NvResult::Success; |
| 217 | if (!params.offset) { | 235 | if (!params.offset) { |
| 218 | LOG_CRITICAL(Service_NVDRV, "failed to map size={}", size); | 236 | LOG_CRITICAL(Service_NVDRV, "failed to map size={}", size); |
| 219 | result = NvErrCodes::InvalidInput; | 237 | result = NvResult::InvalidState; |
| 220 | } else { | 238 | } else { |
| 221 | AddBufferMap(params.offset, size, physical_address, is_alloc); | 239 | AddBufferMap(params.offset, size, physical_address, is_alloc); |
| 222 | } | 240 | } |
| @@ -225,7 +243,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 225 | return result; | 243 | return result; |
| 226 | } | 244 | } |
| 227 | 245 | ||
| 228 | u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | 246 | NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { |
| 229 | IoctlUnmapBuffer params{}; | 247 | IoctlUnmapBuffer params{}; |
| 230 | std::memcpy(¶ms, input.data(), input.size()); | 248 | std::memcpy(¶ms, input.data(), input.size()); |
| 231 | 249 | ||
| @@ -238,20 +256,42 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 238 | } | 256 | } |
| 239 | 257 | ||
| 240 | std::memcpy(output.data(), ¶ms, output.size()); | 258 | std::memcpy(output.data(), ¶ms, output.size()); |
| 241 | return NvErrCodes::Success; | 259 | return NvResult::Success; |
| 242 | } | 260 | } |
| 243 | 261 | ||
| 244 | u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { | 262 | NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { |
| 245 | IoctlBindChannel params{}; | 263 | IoctlBindChannel params{}; |
| 246 | std::memcpy(¶ms, input.data(), input.size()); | 264 | std::memcpy(¶ms, input.data(), input.size()); |
| 247 | 265 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}", params.fd); | |
| 248 | LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); | ||
| 249 | 266 | ||
| 250 | channel = params.fd; | 267 | channel = params.fd; |
| 251 | return 0; | 268 | return NvResult::Success; |
| 269 | } | ||
| 270 | |||
| 271 | NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 272 | IoctlGetVaRegions params{}; | ||
| 273 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 274 | |||
| 275 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | ||
| 276 | params.buf_size); | ||
| 277 | |||
| 278 | params.buf_size = 0x30; | ||
| 279 | params.regions[0].offset = 0x04000000; | ||
| 280 | params.regions[0].page_size = 0x1000; | ||
| 281 | params.regions[0].pages = 0x3fbfff; | ||
| 282 | |||
| 283 | params.regions[1].offset = 0x04000000; | ||
| 284 | params.regions[1].page_size = 0x10000; | ||
| 285 | params.regions[1].pages = 0x1bffff; | ||
| 286 | |||
| 287 | // TODO(ogniK): This probably can stay stubbed but should add support way way later | ||
| 288 | |||
| 289 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 290 | return NvResult::Success; | ||
| 252 | } | 291 | } |
| 253 | 292 | ||
| 254 | u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { | 293 | NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, |
| 294 | std::vector<u8>& inline_output) { | ||
| 255 | IoctlGetVaRegions params{}; | 295 | IoctlGetVaRegions params{}; |
| 256 | std::memcpy(¶ms, input.data(), input.size()); | 296 | std::memcpy(¶ms, input.data(), input.size()); |
| 257 | 297 | ||
| @@ -270,7 +310,8 @@ u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& o | |||
| 270 | // TODO(ogniK): This probably can stay stubbed but should add support way way later | 310 | // TODO(ogniK): This probably can stay stubbed but should add support way way later |
| 271 | 311 | ||
| 272 | std::memcpy(output.data(), ¶ms, output.size()); | 312 | std::memcpy(output.data(), ¶ms, output.size()); |
| 273 | return 0; | 313 | std::memcpy(inline_output.data(), ¶ms.regions, inline_output.size()); |
| 314 | return NvResult::Success; | ||
| 274 | } | 315 | } |
| 275 | 316 | ||
| 276 | std::optional<nvhost_as_gpu::BufferMap> nvhost_as_gpu::FindBufferMap(GPUVAddr gpu_addr) const { | 317 | std::optional<nvhost_as_gpu::BufferMap> nvhost_as_gpu::FindBufferMap(GPUVAddr gpu_addr) const { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index fcdb40d93..08035fa0e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -30,9 +30,11 @@ public: | |||
| 30 | explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 30 | explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 31 | ~nvhost_as_gpu() override; | 31 | ~nvhost_as_gpu() override; |
| 32 | 32 | ||
| 33 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 33 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 34 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 34 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 35 | IoctlVersion version) override; | 35 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 36 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 37 | std::vector<u8>& inline_output) override; | ||
| 36 | 38 | ||
| 37 | private: | 39 | private: |
| 38 | class BufferMap final { | 40 | class BufferMap final { |
| @@ -74,32 +76,21 @@ private: | |||
| 74 | bool is_allocated{}; | 76 | bool is_allocated{}; |
| 75 | }; | 77 | }; |
| 76 | 78 | ||
| 77 | enum class IoctlCommand : u32_le { | ||
| 78 | IocInitalizeExCommand = 0x40284109, | ||
| 79 | IocAllocateSpaceCommand = 0xC0184102, | ||
| 80 | IocRemapCommand = 0x00000014, | ||
| 81 | IocMapBufferExCommand = 0xC0284106, | ||
| 82 | IocBindChannelCommand = 0x40044101, | ||
| 83 | IocGetVaRegionsCommand = 0xC0404108, | ||
| 84 | IocUnmapBufferCommand = 0xC0084105, | ||
| 85 | IocFreeSpaceCommand = 0xC0104103, | ||
| 86 | }; | ||
| 87 | |||
| 88 | struct IoctlInitalizeEx { | 79 | struct IoctlInitalizeEx { |
| 89 | u32_le big_page_size; // depends on GPU's available_big_page_sizes; 0=default | 80 | u32_le big_page_size{}; // depends on GPU's available_big_page_sizes; 0=default |
| 90 | s32_le as_fd; // ignored; passes 0 | 81 | s32_le as_fd{}; // ignored; passes 0 |
| 91 | u32_le flags; // passes 0 | 82 | u32_le flags{}; // passes 0 |
| 92 | u32_le reserved; // ignored; passes 0 | 83 | u32_le reserved{}; // ignored; passes 0 |
| 93 | u64_le unk0; | 84 | u64_le unk0{}; |
| 94 | u64_le unk1; | 85 | u64_le unk1{}; |
| 95 | u64_le unk2; | 86 | u64_le unk2{}; |
| 96 | }; | 87 | }; |
| 97 | static_assert(sizeof(IoctlInitalizeEx) == 40, "IoctlInitalizeEx is incorrect size"); | 88 | static_assert(sizeof(IoctlInitalizeEx) == 40, "IoctlInitalizeEx is incorrect size"); |
| 98 | 89 | ||
| 99 | struct IoctlAllocSpace { | 90 | struct IoctlAllocSpace { |
| 100 | u32_le pages; | 91 | u32_le pages{}; |
| 101 | u32_le page_size; | 92 | u32_le page_size{}; |
| 102 | AddressSpaceFlags flags; | 93 | AddressSpaceFlags flags{}; |
| 103 | INSERT_PADDING_WORDS(1); | 94 | INSERT_PADDING_WORDS(1); |
| 104 | union { | 95 | union { |
| 105 | u64_le offset; | 96 | u64_le offset; |
| @@ -109,70 +100,73 @@ private: | |||
| 109 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); | 100 | static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); |
| 110 | 101 | ||
| 111 | struct IoctlFreeSpace { | 102 | struct IoctlFreeSpace { |
| 112 | u64_le offset; | 103 | u64_le offset{}; |
| 113 | u32_le pages; | 104 | u32_le pages{}; |
| 114 | u32_le page_size; | 105 | u32_le page_size{}; |
| 115 | }; | 106 | }; |
| 116 | static_assert(sizeof(IoctlFreeSpace) == 16, "IoctlFreeSpace is incorrect size"); | 107 | static_assert(sizeof(IoctlFreeSpace) == 16, "IoctlFreeSpace is incorrect size"); |
| 117 | 108 | ||
| 118 | struct IoctlRemapEntry { | 109 | struct IoctlRemapEntry { |
| 119 | u16_le flags; | 110 | u16_le flags{}; |
| 120 | u16_le kind; | 111 | u16_le kind{}; |
| 121 | u32_le nvmap_handle; | 112 | u32_le nvmap_handle{}; |
| 122 | u32_le map_offset; | 113 | u32_le map_offset{}; |
| 123 | u32_le offset; | 114 | u32_le offset{}; |
| 124 | u32_le pages; | 115 | u32_le pages{}; |
| 125 | }; | 116 | }; |
| 126 | static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size"); | 117 | static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size"); |
| 127 | 118 | ||
| 128 | struct IoctlMapBufferEx { | 119 | struct IoctlMapBufferEx { |
| 129 | AddressSpaceFlags flags; // bit0: fixed_offset, bit2: cacheable | 120 | AddressSpaceFlags flags{}; // bit0: fixed_offset, bit2: cacheable |
| 130 | u32_le kind; // -1 is default | 121 | u32_le kind{}; // -1 is default |
| 131 | u32_le nvmap_handle; | 122 | u32_le nvmap_handle{}; |
| 132 | u32_le page_size; // 0 means don't care | 123 | u32_le page_size{}; // 0 means don't care |
| 133 | s64_le buffer_offset; | 124 | s64_le buffer_offset{}; |
| 134 | u64_le mapping_size; | 125 | u64_le mapping_size{}; |
| 135 | s64_le offset; | 126 | s64_le offset{}; |
| 136 | }; | 127 | }; |
| 137 | static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size"); | 128 | static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size"); |
| 138 | 129 | ||
| 139 | struct IoctlUnmapBuffer { | 130 | struct IoctlUnmapBuffer { |
| 140 | s64_le offset; | 131 | s64_le offset{}; |
| 141 | }; | 132 | }; |
| 142 | static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size"); | 133 | static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size"); |
| 143 | 134 | ||
| 144 | struct IoctlBindChannel { | 135 | struct IoctlBindChannel { |
| 145 | u32_le fd; | 136 | s32_le fd{}; |
| 146 | }; | 137 | }; |
| 147 | static_assert(sizeof(IoctlBindChannel) == 4, "IoctlBindChannel is incorrect size"); | 138 | static_assert(sizeof(IoctlBindChannel) == 4, "IoctlBindChannel is incorrect size"); |
| 148 | 139 | ||
| 149 | struct IoctlVaRegion { | 140 | struct IoctlVaRegion { |
| 150 | u64_le offset; | 141 | u64_le offset{}; |
| 151 | u32_le page_size; | 142 | u32_le page_size{}; |
| 152 | INSERT_PADDING_WORDS(1); | 143 | INSERT_PADDING_WORDS(1); |
| 153 | u64_le pages; | 144 | u64_le pages{}; |
| 154 | }; | 145 | }; |
| 155 | static_assert(sizeof(IoctlVaRegion) == 24, "IoctlVaRegion is incorrect size"); | 146 | static_assert(sizeof(IoctlVaRegion) == 24, "IoctlVaRegion is incorrect size"); |
| 156 | 147 | ||
| 157 | struct IoctlGetVaRegions { | 148 | struct IoctlGetVaRegions { |
| 158 | u64_le buf_addr; // (contained output user ptr on linux, ignored) | 149 | u64_le buf_addr{}; // (contained output user ptr on linux, ignored) |
| 159 | u32_le buf_size; // forced to 2*sizeof(struct va_region) | 150 | u32_le buf_size{}; // forced to 2*sizeof(struct va_region) |
| 160 | u32_le reserved; | 151 | u32_le reserved{}; |
| 161 | IoctlVaRegion regions[2]; | 152 | IoctlVaRegion regions[2]{}; |
| 162 | }; | 153 | }; |
| 163 | static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2, | 154 | static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2, |
| 164 | "IoctlGetVaRegions is incorrect size"); | 155 | "IoctlGetVaRegions is incorrect size"); |
| 165 | 156 | ||
| 166 | u32 channel{}; | 157 | s32 channel{}; |
| 158 | |||
| 159 | NvResult InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 160 | NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 161 | NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 162 | NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 163 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 164 | NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 165 | NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 167 | 166 | ||
| 168 | u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); | 167 | NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); |
| 169 | u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); | 168 | NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, |
| 170 | u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); | 169 | std::vector<u8>& inline_output); |
| 171 | u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 172 | u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 173 | u32 FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 174 | u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 175 | u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 176 | 170 | ||
| 177 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; | 171 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; |
| 178 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); | 172 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 8356a8139..d90cf90a8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -20,41 +20,54 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface, | |||
| 20 | : nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {} | 20 | : nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {} |
| 21 | nvhost_ctrl::~nvhost_ctrl() = default; | 21 | nvhost_ctrl::~nvhost_ctrl() = default; |
| 22 | 22 | ||
| 23 | u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 23 | NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { |
| 24 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 24 | switch (command.group) { |
| 25 | IoctlVersion version) { | 25 | case 0x0: |
| 26 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 26 | switch (command.cmd) { |
| 27 | command.raw, input.size(), output.size()); | 27 | case 0x1b: |
| 28 | 28 | return NvOsGetConfigU32(input, output); | |
| 29 | switch (static_cast<IoctlCommand>(command.raw)) { | 29 | case 0x1c: |
| 30 | case IoctlCommand::IocGetConfigCommand: | 30 | return IocCtrlClearEventWait(input, output); |
| 31 | return NvOsGetConfigU32(input, output); | 31 | case 0x1d: |
| 32 | case IoctlCommand::IocCtrlEventWaitCommand: | 32 | return IocCtrlEventWait(input, output, false); |
| 33 | return IocCtrlEventWait(input, output, false, ctrl); | 33 | case 0x1e: |
| 34 | case IoctlCommand::IocCtrlEventWaitAsyncCommand: | 34 | return IocCtrlEventWait(input, output, true); |
| 35 | return IocCtrlEventWait(input, output, true, ctrl); | 35 | case 0x1f: |
| 36 | case IoctlCommand::IocCtrlEventRegisterCommand: | 36 | return IocCtrlEventRegister(input, output); |
| 37 | return IocCtrlEventRegister(input, output); | 37 | case 0x20: |
| 38 | case IoctlCommand::IocCtrlEventUnregisterCommand: | 38 | return IocCtrlEventUnregister(input, output); |
| 39 | return IocCtrlEventUnregister(input, output); | 39 | } |
| 40 | case IoctlCommand::IocCtrlClearEventWaitCommand: | 40 | break; |
| 41 | return IocCtrlClearEventWait(input, output); | ||
| 42 | default: | 41 | default: |
| 43 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 42 | break; |
| 44 | return 0; | ||
| 45 | } | 43 | } |
| 44 | |||
| 45 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 46 | return NvResult::NotImplemented; | ||
| 47 | } | ||
| 48 | |||
| 49 | NvResult nvhost_ctrl::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 50 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 51 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 52 | return NvResult::NotImplemented; | ||
| 53 | } | ||
| 54 | |||
| 55 | NvResult nvhost_ctrl::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 56 | std::vector<u8>& inline_output) { | ||
| 57 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 58 | return NvResult::NotImplemented; | ||
| 46 | } | 59 | } |
| 47 | 60 | ||
| 48 | u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { | 61 | NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { |
| 49 | IocGetConfigParams params{}; | 62 | IocGetConfigParams params{}; |
| 50 | std::memcpy(¶ms, input.data(), sizeof(params)); | 63 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 51 | LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), | 64 | LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), |
| 52 | params.param_str.data()); | 65 | params.param_str.data()); |
| 53 | return 0x30006; // Returns error on production mode | 66 | return NvResult::ConfigVarNotFound; // Returns error on production mode |
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, | 69 | NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, |
| 57 | bool is_async, IoctlCtrl& ctrl) { | 70 | bool is_async) { |
| 58 | IocCtrlEventWaitParams params{}; | 71 | IocCtrlEventWaitParams params{}; |
| 59 | std::memcpy(¶ms, input.data(), sizeof(params)); | 72 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 60 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}", | 73 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}", |
| @@ -126,10 +139,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | |||
| 126 | params.value |= event_id; | 139 | params.value |= event_id; |
| 127 | event.event.writable->Clear(); | 140 | event.event.writable->Clear(); |
| 128 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); | 141 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); |
| 129 | if (!is_async && ctrl.fresh_call) { | 142 | if (!is_async) { |
| 130 | ctrl.must_delay = true; | ||
| 131 | ctrl.timeout = params.timeout; | ||
| 132 | ctrl.event_id = event_id; | ||
| 133 | return NvResult::Timeout; | 143 | return NvResult::Timeout; |
| 134 | } | 144 | } |
| 135 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 145 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| @@ -139,7 +149,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | |||
| 139 | return NvResult::BadParameter; | 149 | return NvResult::BadParameter; |
| 140 | } | 150 | } |
| 141 | 151 | ||
| 142 | u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { | 152 | NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { |
| 143 | IocCtrlEventRegisterParams params{}; | 153 | IocCtrlEventRegisterParams params{}; |
| 144 | std::memcpy(¶ms, input.data(), sizeof(params)); | 154 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 145 | const u32 event_id = params.user_event_id & 0x00FF; | 155 | const u32 event_id = params.user_event_id & 0x00FF; |
| @@ -154,7 +164,8 @@ u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector< | |||
| 154 | return NvResult::Success; | 164 | return NvResult::Success; |
| 155 | } | 165 | } |
| 156 | 166 | ||
| 157 | u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output) { | 167 | NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, |
| 168 | std::vector<u8>& output) { | ||
| 158 | IocCtrlEventUnregisterParams params{}; | 169 | IocCtrlEventUnregisterParams params{}; |
| 159 | std::memcpy(¶ms, input.data(), sizeof(params)); | 170 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 160 | const u32 event_id = params.user_event_id & 0x00FF; | 171 | const u32 event_id = params.user_event_id & 0x00FF; |
| @@ -169,7 +180,7 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vecto | |||
| 169 | return NvResult::Success; | 180 | return NvResult::Success; |
| 170 | } | 181 | } |
| 171 | 182 | ||
| 172 | u32 nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { | 183 | NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { |
| 173 | IocCtrlEventSignalParams params{}; | 184 | IocCtrlEventSignalParams params{}; |
| 174 | std::memcpy(¶ms, input.data(), sizeof(params)); | 185 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 175 | 186 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 24ad96cb9..c5aa1362a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -18,132 +18,113 @@ public: | |||
| 18 | SyncpointManager& syncpoint_manager); | 18 | SyncpointManager& syncpoint_manager); |
| 19 | ~nvhost_ctrl() override; | 19 | ~nvhost_ctrl() override; |
| 20 | 20 | ||
| 21 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 21 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 22 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 22 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 23 | IoctlVersion version) override; | 23 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 24 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 25 | std::vector<u8>& inline_output) override; | ||
| 24 | 26 | ||
| 25 | private: | 27 | private: |
| 26 | enum class IoctlCommand : u32_le { | ||
| 27 | IocSyncptReadCommand = 0xC0080014, | ||
| 28 | IocSyncptIncrCommand = 0x40040015, | ||
| 29 | IocSyncptWaitCommand = 0xC00C0016, | ||
| 30 | IocModuleMutexCommand = 0x40080017, | ||
| 31 | IocModuleRegRDWRCommand = 0xC0180018, | ||
| 32 | IocSyncptWaitexCommand = 0xC0100019, | ||
| 33 | IocSyncptReadMaxCommand = 0xC008001A, | ||
| 34 | IocGetConfigCommand = 0xC183001B, | ||
| 35 | IocCtrlClearEventWaitCommand = 0xC004001C, | ||
| 36 | IocCtrlEventWaitCommand = 0xC010001D, | ||
| 37 | IocCtrlEventWaitAsyncCommand = 0xC010001E, | ||
| 38 | IocCtrlEventRegisterCommand = 0xC004001F, | ||
| 39 | IocCtrlEventUnregisterCommand = 0xC0040020, | ||
| 40 | IocCtrlEventKillCommand = 0x40080021, | ||
| 41 | }; | ||
| 42 | struct IocSyncptReadParams { | 28 | struct IocSyncptReadParams { |
| 43 | u32_le id; | 29 | u32_le id{}; |
| 44 | u32_le value; | 30 | u32_le value{}; |
| 45 | }; | 31 | }; |
| 46 | static_assert(sizeof(IocSyncptReadParams) == 8, "IocSyncptReadParams is incorrect size"); | 32 | static_assert(sizeof(IocSyncptReadParams) == 8, "IocSyncptReadParams is incorrect size"); |
| 47 | 33 | ||
| 48 | struct IocSyncptIncrParams { | 34 | struct IocSyncptIncrParams { |
| 49 | u32_le id; | 35 | u32_le id{}; |
| 50 | }; | 36 | }; |
| 51 | static_assert(sizeof(IocSyncptIncrParams) == 4, "IocSyncptIncrParams is incorrect size"); | 37 | static_assert(sizeof(IocSyncptIncrParams) == 4, "IocSyncptIncrParams is incorrect size"); |
| 52 | 38 | ||
| 53 | struct IocSyncptWaitParams { | 39 | struct IocSyncptWaitParams { |
| 54 | u32_le id; | 40 | u32_le id{}; |
| 55 | u32_le thresh; | 41 | u32_le thresh{}; |
| 56 | s32_le timeout; | 42 | s32_le timeout{}; |
| 57 | }; | 43 | }; |
| 58 | static_assert(sizeof(IocSyncptWaitParams) == 12, "IocSyncptWaitParams is incorrect size"); | 44 | static_assert(sizeof(IocSyncptWaitParams) == 12, "IocSyncptWaitParams is incorrect size"); |
| 59 | 45 | ||
| 60 | struct IocModuleMutexParams { | 46 | struct IocModuleMutexParams { |
| 61 | u32_le id; | 47 | u32_le id{}; |
| 62 | u32_le lock; // (0 = unlock and 1 = lock) | 48 | u32_le lock{}; // (0 = unlock and 1 = lock) |
| 63 | }; | 49 | }; |
| 64 | static_assert(sizeof(IocModuleMutexParams) == 8, "IocModuleMutexParams is incorrect size"); | 50 | static_assert(sizeof(IocModuleMutexParams) == 8, "IocModuleMutexParams is incorrect size"); |
| 65 | 51 | ||
| 66 | struct IocModuleRegRDWRParams { | 52 | struct IocModuleRegRDWRParams { |
| 67 | u32_le id; | 53 | u32_le id{}; |
| 68 | u32_le num_offsets; | 54 | u32_le num_offsets{}; |
| 69 | u32_le block_size; | 55 | u32_le block_size{}; |
| 70 | u32_le offsets; | 56 | u32_le offsets{}; |
| 71 | u32_le values; | 57 | u32_le values{}; |
| 72 | u32_le write; | 58 | u32_le write{}; |
| 73 | }; | 59 | }; |
| 74 | static_assert(sizeof(IocModuleRegRDWRParams) == 24, "IocModuleRegRDWRParams is incorrect size"); | 60 | static_assert(sizeof(IocModuleRegRDWRParams) == 24, "IocModuleRegRDWRParams is incorrect size"); |
| 75 | 61 | ||
| 76 | struct IocSyncptWaitexParams { | 62 | struct IocSyncptWaitexParams { |
| 77 | u32_le id; | 63 | u32_le id{}; |
| 78 | u32_le thresh; | 64 | u32_le thresh{}; |
| 79 | s32_le timeout; | 65 | s32_le timeout{}; |
| 80 | u32_le value; | 66 | u32_le value{}; |
| 81 | }; | 67 | }; |
| 82 | static_assert(sizeof(IocSyncptWaitexParams) == 16, "IocSyncptWaitexParams is incorrect size"); | 68 | static_assert(sizeof(IocSyncptWaitexParams) == 16, "IocSyncptWaitexParams is incorrect size"); |
| 83 | 69 | ||
| 84 | struct IocSyncptReadMaxParams { | 70 | struct IocSyncptReadMaxParams { |
| 85 | u32_le id; | 71 | u32_le id{}; |
| 86 | u32_le value; | 72 | u32_le value{}; |
| 87 | }; | 73 | }; |
| 88 | static_assert(sizeof(IocSyncptReadMaxParams) == 8, "IocSyncptReadMaxParams is incorrect size"); | 74 | static_assert(sizeof(IocSyncptReadMaxParams) == 8, "IocSyncptReadMaxParams is incorrect size"); |
| 89 | 75 | ||
| 90 | struct IocGetConfigParams { | 76 | struct IocGetConfigParams { |
| 91 | std::array<char, 0x41> domain_str; | 77 | std::array<char, 0x41> domain_str{}; |
| 92 | std::array<char, 0x41> param_str; | 78 | std::array<char, 0x41> param_str{}; |
| 93 | std::array<char, 0x101> config_str; | 79 | std::array<char, 0x101> config_str{}; |
| 94 | }; | 80 | }; |
| 95 | static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size"); | 81 | static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size"); |
| 96 | 82 | ||
| 97 | struct IocCtrlEventSignalParams { | 83 | struct IocCtrlEventSignalParams { |
| 98 | u32_le event_id; | 84 | u32_le event_id{}; |
| 99 | }; | 85 | }; |
| 100 | static_assert(sizeof(IocCtrlEventSignalParams) == 4, | 86 | static_assert(sizeof(IocCtrlEventSignalParams) == 4, |
| 101 | "IocCtrlEventSignalParams is incorrect size"); | 87 | "IocCtrlEventSignalParams is incorrect size"); |
| 102 | 88 | ||
| 103 | struct IocCtrlEventWaitParams { | 89 | struct IocCtrlEventWaitParams { |
| 104 | u32_le syncpt_id; | 90 | u32_le syncpt_id{}; |
| 105 | u32_le threshold; | 91 | u32_le threshold{}; |
| 106 | s32_le timeout; | 92 | s32_le timeout{}; |
| 107 | u32_le value; | 93 | u32_le value{}; |
| 108 | }; | 94 | }; |
| 109 | static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size"); | 95 | static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size"); |
| 110 | 96 | ||
| 111 | struct IocCtrlEventWaitAsyncParams { | 97 | struct IocCtrlEventWaitAsyncParams { |
| 112 | u32_le syncpt_id; | 98 | u32_le syncpt_id{}; |
| 113 | u32_le threshold; | 99 | u32_le threshold{}; |
| 114 | u32_le timeout; | 100 | u32_le timeout{}; |
| 115 | u32_le value; | 101 | u32_le value{}; |
| 116 | }; | 102 | }; |
| 117 | static_assert(sizeof(IocCtrlEventWaitAsyncParams) == 16, | 103 | static_assert(sizeof(IocCtrlEventWaitAsyncParams) == 16, |
| 118 | "IocCtrlEventWaitAsyncParams is incorrect size"); | 104 | "IocCtrlEventWaitAsyncParams is incorrect size"); |
| 119 | 105 | ||
| 120 | struct IocCtrlEventRegisterParams { | 106 | struct IocCtrlEventRegisterParams { |
| 121 | u32_le user_event_id; | 107 | u32_le user_event_id{}; |
| 122 | }; | 108 | }; |
| 123 | static_assert(sizeof(IocCtrlEventRegisterParams) == 4, | 109 | static_assert(sizeof(IocCtrlEventRegisterParams) == 4, |
| 124 | "IocCtrlEventRegisterParams is incorrect size"); | 110 | "IocCtrlEventRegisterParams is incorrect size"); |
| 125 | 111 | ||
| 126 | struct IocCtrlEventUnregisterParams { | 112 | struct IocCtrlEventUnregisterParams { |
| 127 | u32_le user_event_id; | 113 | u32_le user_event_id{}; |
| 128 | }; | 114 | }; |
| 129 | static_assert(sizeof(IocCtrlEventUnregisterParams) == 4, | 115 | static_assert(sizeof(IocCtrlEventUnregisterParams) == 4, |
| 130 | "IocCtrlEventUnregisterParams is incorrect size"); | 116 | "IocCtrlEventUnregisterParams is incorrect size"); |
| 131 | 117 | ||
| 132 | struct IocCtrlEventKill { | 118 | struct IocCtrlEventKill { |
| 133 | u64_le user_events; | 119 | u64_le user_events{}; |
| 134 | }; | 120 | }; |
| 135 | static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size"); | 121 | static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size"); |
| 136 | 122 | ||
| 137 | u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); | 123 | NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); |
| 138 | 124 | NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async); | |
| 139 | u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async, | 125 | NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); |
| 140 | IoctlCtrl& ctrl); | 126 | NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); |
| 141 | 127 | NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); | |
| 142 | u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 143 | |||
| 144 | u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 145 | |||
| 146 | u32 IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 147 | 128 | ||
| 148 | EventInterface& events_interface; | 129 | EventInterface& events_interface; |
| 149 | SyncpointManager& syncpoint_manager; | 130 | SyncpointManager& syncpoint_manager; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index fba89e7a6..2d7ea433c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -15,39 +15,66 @@ namespace Service::Nvidia::Devices { | |||
| 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {} | 15 | nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {} |
| 16 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; | 16 | nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; |
| 17 | 17 | ||
| 18 | u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, | 18 | NvResult nvhost_ctrl_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 19 | const std::vector<u8>& input2, std::vector<u8>& output, | 19 | std::vector<u8>& output) { |
| 20 | std::vector<u8>& output2, IoctlCtrl& ctrl, IoctlVersion version) { | 20 | switch (command.group) { |
| 21 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 21 | case 'G': |
| 22 | command.raw, input.size(), output.size()); | 22 | switch (command.cmd) { |
| 23 | 23 | case 0x1: | |
| 24 | switch (static_cast<IoctlCommand>(command.raw)) { | 24 | return ZCullGetCtxSize(input, output); |
| 25 | case IoctlCommand::IocGetCharacteristicsCommand: | 25 | case 0x2: |
| 26 | return GetCharacteristics(input, output, output2, version); | 26 | return ZCullGetInfo(input, output); |
| 27 | case IoctlCommand::IocGetTPCMasksCommand: | 27 | case 0x3: |
| 28 | return GetTPCMasks(input, output, output2, version); | 28 | return ZBCSetTable(input, output); |
| 29 | case IoctlCommand::IocGetActiveSlotMaskCommand: | 29 | case 0x4: |
| 30 | return GetActiveSlotMask(input, output); | 30 | return ZBCQueryTable(input, output); |
| 31 | case IoctlCommand::IocZcullGetCtxSizeCommand: | 31 | case 0x5: |
| 32 | return ZCullGetCtxSize(input, output); | 32 | return GetCharacteristics(input, output); |
| 33 | case IoctlCommand::IocZcullGetInfo: | 33 | case 0x6: |
| 34 | return ZCullGetInfo(input, output); | 34 | return GetTPCMasks(input, output); |
| 35 | case IoctlCommand::IocZbcSetTable: | 35 | case 0x7: |
| 36 | return ZBCSetTable(input, output); | 36 | return FlushL2(input, output); |
| 37 | case IoctlCommand::IocZbcQueryTable: | 37 | case 0x14: |
| 38 | return ZBCQueryTable(input, output); | 38 | return GetActiveSlotMask(input, output); |
| 39 | case IoctlCommand::IocFlushL2: | 39 | case 0x1c: |
| 40 | return FlushL2(input, output); | 40 | return GetGpuTime(input, output); |
| 41 | case IoctlCommand::IocGetGpuTime: | 41 | default: |
| 42 | return GetGpuTime(input, output); | 42 | break; |
| 43 | } | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 47 | return NvResult::NotImplemented; | ||
| 48 | } | ||
| 49 | |||
| 50 | NvResult nvhost_ctrl_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 51 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 52 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 53 | return NvResult::NotImplemented; | ||
| 54 | } | ||
| 55 | |||
| 56 | NvResult nvhost_ctrl_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, | ||
| 57 | std::vector<u8>& output, std::vector<u8>& inline_output) { | ||
| 58 | switch (command.group) { | ||
| 59 | case 'G': | ||
| 60 | switch (command.cmd) { | ||
| 61 | case 0x5: | ||
| 62 | return GetCharacteristics(input, output, inline_output); | ||
| 63 | case 0x6: | ||
| 64 | return GetTPCMasks(input, output, inline_output); | ||
| 65 | default: | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | break; | ||
| 43 | default: | 69 | default: |
| 44 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 70 | break; |
| 45 | return 0; | ||
| 46 | } | 71 | } |
| 72 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 73 | return NvResult::NotImplemented; | ||
| 47 | } | 74 | } |
| 48 | 75 | ||
| 49 | u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, | 76 | NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, |
| 50 | std::vector<u8>& output2, IoctlVersion version) { | 77 | std::vector<u8>& output) { |
| 51 | LOG_DEBUG(Service_NVDRV, "called"); | 78 | LOG_DEBUG(Service_NVDRV, "called"); |
| 52 | IoctlCharacteristics params{}; | 79 | IoctlCharacteristics params{}; |
| 53 | std::memcpy(¶ms, input.data(), input.size()); | 80 | std::memcpy(¶ms, input.data(), input.size()); |
| @@ -88,36 +115,83 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto | |||
| 88 | params.gc.gr_compbit_store_base_hw = 0x0; | 115 | params.gc.gr_compbit_store_base_hw = 0x0; |
| 89 | params.gpu_characteristics_buf_size = 0xA0; | 116 | params.gpu_characteristics_buf_size = 0xA0; |
| 90 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | 117 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) |
| 118 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 119 | return NvResult::Success; | ||
| 120 | } | ||
| 91 | 121 | ||
| 92 | if (version == IoctlVersion::Version3) { | 122 | NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, |
| 93 | std::memcpy(output.data(), input.data(), output.size()); | 123 | std::vector<u8>& inline_output) { |
| 94 | std::memcpy(output2.data(), ¶ms.gc, output2.size()); | 124 | LOG_DEBUG(Service_NVDRV, "called"); |
| 95 | } else { | 125 | IoctlCharacteristics params{}; |
| 96 | std::memcpy(output.data(), ¶ms, output.size()); | 126 | std::memcpy(¶ms, input.data(), input.size()); |
| 97 | } | 127 | params.gc.arch = 0x120; |
| 98 | return 0; | 128 | params.gc.impl = 0xb; |
| 129 | params.gc.rev = 0xa1; | ||
| 130 | params.gc.num_gpc = 0x1; | ||
| 131 | params.gc.l2_cache_size = 0x40000; | ||
| 132 | params.gc.on_board_video_memory_size = 0x0; | ||
| 133 | params.gc.num_tpc_per_gpc = 0x2; | ||
| 134 | params.gc.bus_type = 0x20; | ||
| 135 | params.gc.big_page_size = 0x20000; | ||
| 136 | params.gc.compression_page_size = 0x20000; | ||
| 137 | params.gc.pde_coverage_bit_count = 0x1B; | ||
| 138 | params.gc.available_big_page_sizes = 0x30000; | ||
| 139 | params.gc.gpc_mask = 0x1; | ||
| 140 | params.gc.sm_arch_sm_version = 0x503; | ||
| 141 | params.gc.sm_arch_spa_version = 0x503; | ||
| 142 | params.gc.sm_arch_warp_count = 0x80; | ||
| 143 | params.gc.gpu_va_bit_count = 0x28; | ||
| 144 | params.gc.reserved = 0x0; | ||
| 145 | params.gc.flags = 0x55; | ||
| 146 | params.gc.twod_class = 0x902D; | ||
| 147 | params.gc.threed_class = 0xB197; | ||
| 148 | params.gc.compute_class = 0xB1C0; | ||
| 149 | params.gc.gpfifo_class = 0xB06F; | ||
| 150 | params.gc.inline_to_memory_class = 0xA140; | ||
| 151 | params.gc.dma_copy_class = 0xB0B5; | ||
| 152 | params.gc.max_fbps_count = 0x1; | ||
| 153 | params.gc.fbp_en_mask = 0x0; | ||
| 154 | params.gc.max_ltc_per_fbp = 0x2; | ||
| 155 | params.gc.max_lts_per_ltc = 0x1; | ||
| 156 | params.gc.max_tex_per_tpc = 0x0; | ||
| 157 | params.gc.max_gpc_count = 0x1; | ||
| 158 | params.gc.rop_l2_en_mask_0 = 0x21D70; | ||
| 159 | params.gc.rop_l2_en_mask_1 = 0x0; | ||
| 160 | params.gc.chipname = 0x6230326D67; | ||
| 161 | params.gc.gr_compbit_store_base_hw = 0x0; | ||
| 162 | params.gpu_characteristics_buf_size = 0xA0; | ||
| 163 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | ||
| 164 | |||
| 165 | std::memcpy(output.data(), input.data(), output.size()); | ||
| 166 | std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size()); | ||
| 167 | return NvResult::Success; | ||
| 99 | } | 168 | } |
| 100 | 169 | ||
| 101 | u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, | 170 | NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { |
| 102 | std::vector<u8>& output2, IoctlVersion version) { | ||
| 103 | IoctlGpuGetTpcMasksArgs params{}; | 171 | IoctlGpuGetTpcMasksArgs params{}; |
| 104 | std::memcpy(¶ms, input.data(), input.size()); | 172 | std::memcpy(¶ms, input.data(), input.size()); |
| 105 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | 173 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); |
| 106 | if (params.mask_buffer_size != 0) { | 174 | if (params.mask_buffer_size != 0) { |
| 107 | params.tcp_mask = 3; | 175 | params.tcp_mask = 3; |
| 108 | } | 176 | } |
| 177 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 178 | return NvResult::Success; | ||
| 179 | } | ||
| 109 | 180 | ||
| 110 | if (version == IoctlVersion::Version3) { | 181 | NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, |
| 111 | std::memcpy(output.data(), input.data(), output.size()); | 182 | std::vector<u8>& inline_output) { |
| 112 | std::memcpy(output2.data(), ¶ms.tcp_mask, output2.size()); | 183 | IoctlGpuGetTpcMasksArgs params{}; |
| 113 | } else { | 184 | std::memcpy(¶ms, input.data(), input.size()); |
| 114 | std::memcpy(output.data(), ¶ms, output.size()); | 185 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); |
| 186 | if (params.mask_buffer_size != 0) { | ||
| 187 | params.tcp_mask = 3; | ||
| 115 | } | 188 | } |
| 116 | 189 | std::memcpy(output.data(), ¶ms, output.size()); | |
| 117 | return 0; | 190 | std::memcpy(inline_output.data(), ¶ms.tcp_mask, inline_output.size()); |
| 191 | return NvResult::Success; | ||
| 118 | } | 192 | } |
| 119 | 193 | ||
| 120 | u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { | 194 | NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { |
| 121 | LOG_DEBUG(Service_NVDRV, "called"); | 195 | LOG_DEBUG(Service_NVDRV, "called"); |
| 122 | 196 | ||
| 123 | IoctlActiveSlotMask params{}; | 197 | IoctlActiveSlotMask params{}; |
| @@ -127,10 +201,10 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector | |||
| 127 | params.slot = 0x07; | 201 | params.slot = 0x07; |
| 128 | params.mask = 0x01; | 202 | params.mask = 0x01; |
| 129 | std::memcpy(output.data(), ¶ms, output.size()); | 203 | std::memcpy(output.data(), ¶ms, output.size()); |
| 130 | return 0; | 204 | return NvResult::Success; |
| 131 | } | 205 | } |
| 132 | 206 | ||
| 133 | u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { | 207 | NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { |
| 134 | LOG_DEBUG(Service_NVDRV, "called"); | 208 | LOG_DEBUG(Service_NVDRV, "called"); |
| 135 | 209 | ||
| 136 | IoctlZcullGetCtxSize params{}; | 210 | IoctlZcullGetCtxSize params{}; |
| @@ -139,10 +213,10 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u | |||
| 139 | } | 213 | } |
| 140 | params.size = 0x1; | 214 | params.size = 0x1; |
| 141 | std::memcpy(output.data(), ¶ms, output.size()); | 215 | std::memcpy(output.data(), ¶ms, output.size()); |
| 142 | return 0; | 216 | return NvResult::Success; |
| 143 | } | 217 | } |
| 144 | 218 | ||
| 145 | u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { | 219 | NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { |
| 146 | LOG_DEBUG(Service_NVDRV, "called"); | 220 | LOG_DEBUG(Service_NVDRV, "called"); |
| 147 | 221 | ||
| 148 | IoctlNvgpuGpuZcullGetInfoArgs params{}; | 222 | IoctlNvgpuGpuZcullGetInfoArgs params{}; |
| @@ -162,47 +236,47 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& | |||
| 162 | params.subregion_height_align_pixels = 0x40; | 236 | params.subregion_height_align_pixels = 0x40; |
| 163 | params.subregion_count = 0x10; | 237 | params.subregion_count = 0x10; |
| 164 | std::memcpy(output.data(), ¶ms, output.size()); | 238 | std::memcpy(output.data(), ¶ms, output.size()); |
| 165 | return 0; | 239 | return NvResult::Success; |
| 166 | } | 240 | } |
| 167 | 241 | ||
| 168 | u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { | 242 | NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { |
| 169 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 243 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 170 | 244 | ||
| 171 | IoctlZbcSetTable params{}; | 245 | IoctlZbcSetTable params{}; |
| 172 | std::memcpy(¶ms, input.data(), input.size()); | 246 | std::memcpy(¶ms, input.data(), input.size()); |
| 173 | // TODO(ogniK): What does this even actually do? | 247 | // TODO(ogniK): What does this even actually do? |
| 174 | std::memcpy(output.data(), ¶ms, output.size()); | 248 | std::memcpy(output.data(), ¶ms, output.size()); |
| 175 | return 0; | 249 | return NvResult::Success; |
| 176 | } | 250 | } |
| 177 | 251 | ||
| 178 | u32 nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { | 252 | NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { |
| 179 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 253 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 180 | 254 | ||
| 181 | IoctlZbcQueryTable params{}; | 255 | IoctlZbcQueryTable params{}; |
| 182 | std::memcpy(¶ms, input.data(), input.size()); | 256 | std::memcpy(¶ms, input.data(), input.size()); |
| 183 | // TODO : To implement properly | 257 | // TODO : To implement properly |
| 184 | std::memcpy(output.data(), ¶ms, output.size()); | 258 | std::memcpy(output.data(), ¶ms, output.size()); |
| 185 | return 0; | 259 | return NvResult::Success; |
| 186 | } | 260 | } |
| 187 | 261 | ||
| 188 | u32 nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { | 262 | NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { |
| 189 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 263 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 190 | 264 | ||
| 191 | IoctlFlushL2 params{}; | 265 | IoctlFlushL2 params{}; |
| 192 | std::memcpy(¶ms, input.data(), input.size()); | 266 | std::memcpy(¶ms, input.data(), input.size()); |
| 193 | // TODO : To implement properly | 267 | // TODO : To implement properly |
| 194 | std::memcpy(output.data(), ¶ms, output.size()); | 268 | std::memcpy(output.data(), ¶ms, output.size()); |
| 195 | return 0; | 269 | return NvResult::Success; |
| 196 | } | 270 | } |
| 197 | 271 | ||
| 198 | u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { | 272 | NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { |
| 199 | LOG_DEBUG(Service_NVDRV, "called"); | 273 | LOG_DEBUG(Service_NVDRV, "called"); |
| 200 | 274 | ||
| 201 | IoctlGetGpuTime params{}; | 275 | IoctlGetGpuTime params{}; |
| 202 | std::memcpy(¶ms, input.data(), input.size()); | 276 | std::memcpy(¶ms, input.data(), input.size()); |
| 203 | params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); | 277 | params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); |
| 204 | std::memcpy(output.data(), ¶ms, output.size()); | 278 | std::memcpy(output.data(), ¶ms, output.size()); |
| 205 | return 0; | 279 | return NvResult::Success; |
| 206 | } | 280 | } |
| 207 | 281 | ||
| 208 | } // namespace Service::Nvidia::Devices | 282 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index ef60f72ce..137b88238 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | |||
| @@ -16,32 +16,13 @@ public: | |||
| 16 | explicit nvhost_ctrl_gpu(Core::System& system); | 16 | explicit nvhost_ctrl_gpu(Core::System& system); |
| 17 | ~nvhost_ctrl_gpu() override; | 17 | ~nvhost_ctrl_gpu() override; |
| 18 | 18 | ||
| 19 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 19 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 20 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 20 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 21 | IoctlVersion version) override; | 21 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 22 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 23 | std::vector<u8>& inline_output) override; | ||
| 22 | 24 | ||
| 23 | private: | 25 | private: |
| 24 | enum class IoctlCommand : u32_le { | ||
| 25 | IocGetCharacteristicsCommand = 0xC0B04705, | ||
| 26 | IocGetTPCMasksCommand = 0xC0184706, | ||
| 27 | IocGetActiveSlotMaskCommand = 0x80084714, | ||
| 28 | IocZcullGetCtxSizeCommand = 0x80044701, | ||
| 29 | IocZcullGetInfo = 0x80284702, | ||
| 30 | IocZbcSetTable = 0x402C4703, | ||
| 31 | IocZbcQueryTable = 0xC0344704, | ||
| 32 | IocFlushL2 = 0x40084707, | ||
| 33 | IocInvalICache = 0x4008470D, | ||
| 34 | IocSetMmudebugMode = 0x4008470E, | ||
| 35 | IocSetSmDebugMode = 0x4010470F, | ||
| 36 | IocWaitForPause = 0xC0084710, | ||
| 37 | IocGetTcpExceptionEnStatus = 0x80084711, | ||
| 38 | IocNumVsms = 0x80084712, | ||
| 39 | IocVsmsMapping = 0xC0044713, | ||
| 40 | IocGetErrorChannelUserData = 0xC008471B, | ||
| 41 | IocGetGpuTime = 0xC010471C, | ||
| 42 | IocGetCpuTimeCorrelationInfo = 0xC108471D, | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct IoctlGpuCharacteristics { | 26 | struct IoctlGpuCharacteristics { |
| 46 | u32_le arch; // 0x120 (NVGPU_GPU_ARCH_GM200) | 27 | u32_le arch; // 0x120 (NVGPU_GPU_ARCH_GM200) |
| 47 | u32_le impl; // 0xB (NVGPU_GPU_IMPL_GM20B) | 28 | u32_le impl; // 0xB (NVGPU_GPU_IMPL_GM20B) |
| @@ -159,17 +140,21 @@ private: | |||
| 159 | }; | 140 | }; |
| 160 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); | 141 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); |
| 161 | 142 | ||
| 162 | u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, | 143 | NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output); |
| 163 | std::vector<u8>& output2, IoctlVersion version); | 144 | NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, |
| 164 | u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, std::vector<u8>& output2, | 145 | std::vector<u8>& inline_output); |
| 165 | IoctlVersion version); | 146 | |
| 166 | u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); | 147 | NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); |
| 167 | u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); | 148 | NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, |
| 168 | u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); | 149 | std::vector<u8>& inline_output); |
| 169 | u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); | 150 | |
| 170 | u32 ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); | 151 | NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); |
| 171 | u32 FlushL2(const std::vector<u8>& input, std::vector<u8>& output); | 152 | NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); |
| 172 | u32 GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); | 153 | NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); |
| 154 | NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 155 | NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 156 | NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 157 | NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 173 | }; | 158 | }; |
| 174 | 159 | ||
| 175 | } // namespace Service::Nvidia::Devices | 160 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index b1d9d55b5..af8b3d9f1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -23,107 +23,132 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | |||
| 23 | 23 | ||
| 24 | nvhost_gpu::~nvhost_gpu() = default; | 24 | nvhost_gpu::~nvhost_gpu() = default; |
| 25 | 25 | ||
| 26 | u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 26 | NvResult nvhost_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { |
| 27 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 27 | switch (command.group) { |
| 28 | IoctlVersion version) { | 28 | case 0x0: |
| 29 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 29 | switch (command.cmd) { |
| 30 | command.raw, input.size(), output.size()); | 30 | case 0x3: |
| 31 | 31 | return GetWaitbase(input, output); | |
| 32 | switch (static_cast<IoctlCommand>(command.raw)) { | 32 | default: |
| 33 | case IoctlCommand::IocSetNVMAPfdCommand: | 33 | break; |
| 34 | return SetNVMAPfd(input, output); | 34 | } |
| 35 | case IoctlCommand::IocSetClientDataCommand: | 35 | break; |
| 36 | return SetClientData(input, output); | 36 | case 'H': |
| 37 | case IoctlCommand::IocGetClientDataCommand: | 37 | switch (command.cmd) { |
| 38 | return GetClientData(input, output); | 38 | case 0x1: |
| 39 | case IoctlCommand::IocZCullBind: | 39 | return SetNVMAPfd(input, output); |
| 40 | return ZCullBind(input, output); | 40 | case 0x3: |
| 41 | case IoctlCommand::IocSetErrorNotifierCommand: | 41 | return ChannelSetTimeout(input, output); |
| 42 | return SetErrorNotifier(input, output); | 42 | case 0x8: |
| 43 | case IoctlCommand::IocChannelSetPriorityCommand: | 43 | return SubmitGPFIFOBase(input, output, false); |
| 44 | return SetChannelPriority(input, output); | 44 | case 0x9: |
| 45 | case IoctlCommand::IocAllocGPFIFOEx2Command: | 45 | return AllocateObjectContext(input, output); |
| 46 | return AllocGPFIFOEx2(input, output); | 46 | case 0xb: |
| 47 | case IoctlCommand::IocAllocObjCtxCommand: | 47 | return ZCullBind(input, output); |
| 48 | return AllocateObjectContext(input, output); | 48 | case 0xc: |
| 49 | case IoctlCommand::IocChannelGetWaitbaseCommand: | 49 | return SetErrorNotifier(input, output); |
| 50 | return GetWaitbase(input, output); | 50 | case 0xd: |
| 51 | case IoctlCommand::IocChannelSetTimeoutCommand: | 51 | return SetChannelPriority(input, output); |
| 52 | return ChannelSetTimeout(input, output); | 52 | case 0x1a: |
| 53 | case IoctlCommand::IocChannelSetTimeslice: | 53 | return AllocGPFIFOEx2(input, output); |
| 54 | return ChannelSetTimeslice(input, output); | 54 | case 0x1b: |
| 55 | default: | 55 | return SubmitGPFIFOBase(input, output, true); |
| 56 | case 0x1d: | ||
| 57 | return ChannelSetTimeslice(input, output); | ||
| 58 | default: | ||
| 59 | break; | ||
| 60 | } | ||
| 61 | break; | ||
| 62 | case 'G': | ||
| 63 | switch (command.cmd) { | ||
| 64 | case 0x14: | ||
| 65 | return SetClientData(input, output); | ||
| 66 | case 0x15: | ||
| 67 | return GetClientData(input, output); | ||
| 68 | default: | ||
| 69 | break; | ||
| 70 | } | ||
| 56 | break; | 71 | break; |
| 57 | } | 72 | } |
| 73 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 74 | return NvResult::NotImplemented; | ||
| 75 | }; | ||
| 58 | 76 | ||
| 59 | if (command.group == NVGPU_IOCTL_MAGIC) { | 77 | NvResult nvhost_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 60 | if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { | 78 | const std::vector<u8>& inline_input, std::vector<u8>& output) { |
| 61 | return SubmitGPFIFO(input, output); | 79 | switch (command.group) { |
| 62 | } | 80 | case 'H': |
| 63 | if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) { | 81 | switch (command.cmd) { |
| 64 | return KickoffPB(input, output, input2, version); | 82 | case 0x1b: |
| 83 | return SubmitGPFIFOBase(input, inline_input, output); | ||
| 65 | } | 84 | } |
| 85 | break; | ||
| 66 | } | 86 | } |
| 87 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 88 | return NvResult::NotImplemented; | ||
| 89 | } | ||
| 67 | 90 | ||
| 68 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 91 | NvResult nvhost_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, |
| 69 | return 0; | 92 | std::vector<u8>& inline_output) { |
| 70 | }; | 93 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 94 | return NvResult::NotImplemented; | ||
| 95 | } | ||
| 71 | 96 | ||
| 72 | u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | 97 | NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { |
| 73 | IoctlSetNvmapFD params{}; | 98 | IoctlSetNvmapFD params{}; |
| 74 | std::memcpy(¶ms, input.data(), input.size()); | 99 | std::memcpy(¶ms, input.data(), input.size()); |
| 75 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 100 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 76 | 101 | ||
| 77 | nvmap_fd = params.nvmap_fd; | 102 | nvmap_fd = params.nvmap_fd; |
| 78 | return 0; | 103 | return NvResult::Success; |
| 79 | } | 104 | } |
| 80 | 105 | ||
| 81 | u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { | 106 | NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { |
| 82 | LOG_DEBUG(Service_NVDRV, "called"); | 107 | LOG_DEBUG(Service_NVDRV, "called"); |
| 83 | 108 | ||
| 84 | IoctlClientData params{}; | 109 | IoctlClientData params{}; |
| 85 | std::memcpy(¶ms, input.data(), input.size()); | 110 | std::memcpy(¶ms, input.data(), input.size()); |
| 86 | user_data = params.data; | 111 | user_data = params.data; |
| 87 | return 0; | 112 | return NvResult::Success; |
| 88 | } | 113 | } |
| 89 | 114 | ||
| 90 | u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { | 115 | NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { |
| 91 | LOG_DEBUG(Service_NVDRV, "called"); | 116 | LOG_DEBUG(Service_NVDRV, "called"); |
| 92 | 117 | ||
| 93 | IoctlClientData params{}; | 118 | IoctlClientData params{}; |
| 94 | std::memcpy(¶ms, input.data(), input.size()); | 119 | std::memcpy(¶ms, input.data(), input.size()); |
| 95 | params.data = user_data; | 120 | params.data = user_data; |
| 96 | std::memcpy(output.data(), ¶ms, output.size()); | 121 | std::memcpy(output.data(), ¶ms, output.size()); |
| 97 | return 0; | 122 | return NvResult::Success; |
| 98 | } | 123 | } |
| 99 | 124 | ||
| 100 | u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { | 125 | NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { |
| 101 | std::memcpy(&zcull_params, input.data(), input.size()); | 126 | std::memcpy(&zcull_params, input.data(), input.size()); |
| 102 | LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, | 127 | LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, |
| 103 | zcull_params.mode); | 128 | zcull_params.mode); |
| 104 | 129 | ||
| 105 | std::memcpy(output.data(), &zcull_params, output.size()); | 130 | std::memcpy(output.data(), &zcull_params, output.size()); |
| 106 | return 0; | 131 | return NvResult::Success; |
| 107 | } | 132 | } |
| 108 | 133 | ||
| 109 | u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { | 134 | NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { |
| 110 | IoctlSetErrorNotifier params{}; | 135 | IoctlSetErrorNotifier params{}; |
| 111 | std::memcpy(¶ms, input.data(), input.size()); | 136 | std::memcpy(¶ms, input.data(), input.size()); |
| 112 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, | 137 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, |
| 113 | params.size, params.mem); | 138 | params.size, params.mem); |
| 114 | 139 | ||
| 115 | std::memcpy(output.data(), ¶ms, output.size()); | 140 | std::memcpy(output.data(), ¶ms, output.size()); |
| 116 | return 0; | 141 | return NvResult::Success; |
| 117 | } | 142 | } |
| 118 | 143 | ||
| 119 | u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { | 144 | NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { |
| 120 | std::memcpy(&channel_priority, input.data(), input.size()); | 145 | std::memcpy(&channel_priority, input.data(), input.size()); |
| 121 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); | 146 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); |
| 122 | 147 | ||
| 123 | return 0; | 148 | return NvResult::Success; |
| 124 | } | 149 | } |
| 125 | 150 | ||
| 126 | u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { | 151 | NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { |
| 127 | IoctlAllocGpfifoEx2 params{}; | 152 | IoctlAllocGpfifoEx2 params{}; |
| 128 | std::memcpy(¶ms, input.data(), input.size()); | 153 | std::memcpy(¶ms, input.data(), input.size()); |
| 129 | LOG_WARNING(Service_NVDRV, | 154 | LOG_WARNING(Service_NVDRV, |
| @@ -137,10 +162,10 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou | |||
| 137 | params.fence_out = channel_fence; | 162 | params.fence_out = channel_fence; |
| 138 | 163 | ||
| 139 | std::memcpy(output.data(), ¶ms, output.size()); | 164 | std::memcpy(output.data(), ¶ms, output.size()); |
| 140 | return 0; | 165 | return NvResult::Success; |
| 141 | } | 166 | } |
| 142 | 167 | ||
| 143 | u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { | 168 | NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { |
| 144 | IoctlAllocObjCtx params{}; | 169 | IoctlAllocObjCtx params{}; |
| 145 | std::memcpy(¶ms, input.data(), input.size()); | 170 | std::memcpy(¶ms, input.data(), input.size()); |
| 146 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, | 171 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, |
| @@ -148,7 +173,7 @@ u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector< | |||
| 148 | 173 | ||
| 149 | params.obj_id = 0x0; | 174 | params.obj_id = 0x0; |
| 150 | std::memcpy(output.data(), ¶ms, output.size()); | 175 | std::memcpy(output.data(), ¶ms, output.size()); |
| 151 | return 0; | 176 | return NvResult::Success; |
| 152 | } | 177 | } |
| 153 | 178 | ||
| 154 | static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) { | 179 | static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) { |
| @@ -192,8 +217,8 @@ static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(Fence | |||
| 192 | return result; | 217 | return result; |
| 193 | } | 218 | } |
| 194 | 219 | ||
| 195 | u32 nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, | 220 | NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, |
| 196 | Tegra::CommandList&& entries) { | 221 | Tegra::CommandList&& entries) { |
| 197 | LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, | 222 | LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, |
| 198 | params.num_entries, params.flags.raw); | 223 | params.num_entries, params.flags.raw); |
| 199 | 224 | ||
| @@ -227,69 +252,70 @@ u32 nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& out | |||
| 227 | } | 252 | } |
| 228 | 253 | ||
| 229 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); | 254 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); |
| 230 | return 0; | 255 | return NvResult::Success; |
| 231 | } | 256 | } |
| 232 | 257 | ||
| 233 | u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) { | 258 | NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, |
| 259 | bool kickoff) { | ||
| 234 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 260 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { |
| 235 | UNIMPLEMENTED(); | 261 | UNIMPLEMENTED(); |
| 262 | return NvResult::InvalidSize; | ||
| 236 | } | 263 | } |
| 237 | IoctlSubmitGpfifo params{}; | 264 | IoctlSubmitGpfifo params{}; |
| 238 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | 265 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); |
| 239 | |||
| 240 | Tegra::CommandList entries(params.num_entries); | 266 | Tegra::CommandList entries(params.num_entries); |
| 241 | std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], | 267 | |
| 242 | params.num_entries * sizeof(Tegra::CommandListHeader)); | 268 | if (kickoff) { |
| 269 | system.Memory().ReadBlock(params.address, entries.command_lists.data(), | ||
| 270 | params.num_entries * sizeof(Tegra::CommandListHeader)); | ||
| 271 | } else { | ||
| 272 | std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], | ||
| 273 | params.num_entries * sizeof(Tegra::CommandListHeader)); | ||
| 274 | } | ||
| 243 | 275 | ||
| 244 | return SubmitGPFIFOImpl(params, output, std::move(entries)); | 276 | return SubmitGPFIFOImpl(params, output, std::move(entries)); |
| 245 | } | 277 | } |
| 246 | 278 | ||
| 247 | u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, | 279 | NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, |
| 248 | const std::vector<u8>& input2, IoctlVersion version) { | 280 | const std::vector<u8>& input_inline, |
| 281 | std::vector<u8>& output) { | ||
| 249 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 282 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { |
| 250 | UNIMPLEMENTED(); | 283 | UNIMPLEMENTED(); |
| 284 | return NvResult::InvalidSize; | ||
| 251 | } | 285 | } |
| 252 | IoctlSubmitGpfifo params{}; | 286 | IoctlSubmitGpfifo params{}; |
| 253 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | 287 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); |
| 254 | |||
| 255 | Tegra::CommandList entries(params.num_entries); | 288 | Tegra::CommandList entries(params.num_entries); |
| 256 | if (version == IoctlVersion::Version2) { | 289 | std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); |
| 257 | std::memcpy(entries.command_lists.data(), input2.data(), | ||
| 258 | params.num_entries * sizeof(Tegra::CommandListHeader)); | ||
| 259 | } else { | ||
| 260 | system.Memory().ReadBlock(params.address, entries.command_lists.data(), | ||
| 261 | params.num_entries * sizeof(Tegra::CommandListHeader)); | ||
| 262 | } | ||
| 263 | |||
| 264 | return SubmitGPFIFOImpl(params, output, std::move(entries)); | 290 | return SubmitGPFIFOImpl(params, output, std::move(entries)); |
| 265 | } | 291 | } |
| 266 | 292 | ||
| 267 | u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { | 293 | NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { |
| 268 | IoctlGetWaitbase params{}; | 294 | IoctlGetWaitbase params{}; |
| 269 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | 295 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); |
| 270 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | 296 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); |
| 271 | 297 | ||
| 272 | params.value = 0; // Seems to be hard coded at 0 | 298 | params.value = 0; // Seems to be hard coded at 0 |
| 273 | std::memcpy(output.data(), ¶ms, output.size()); | 299 | std::memcpy(output.data(), ¶ms, output.size()); |
| 274 | return 0; | 300 | return NvResult::Success; |
| 275 | } | 301 | } |
| 276 | 302 | ||
| 277 | u32 nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { | 303 | NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { |
| 278 | IoctlChannelSetTimeout params{}; | 304 | IoctlChannelSetTimeout params{}; |
| 279 | std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); | 305 | std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); |
| 280 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); | 306 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); |
| 281 | 307 | ||
| 282 | return 0; | 308 | return NvResult::Success; |
| 283 | } | 309 | } |
| 284 | 310 | ||
| 285 | u32 nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { | 311 | NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { |
| 286 | IoctlSetTimeslice params{}; | 312 | IoctlSetTimeslice params{}; |
| 287 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); | 313 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); |
| 288 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); | 314 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); |
| 289 | 315 | ||
| 290 | channel_timeslice = params.timeslice; | 316 | channel_timeslice = params.timeslice; |
| 291 | 317 | ||
| 292 | return 0; | 318 | return NvResult::Success; |
| 293 | } | 319 | } |
| 294 | 320 | ||
| 295 | } // namespace Service::Nvidia::Devices | 321 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index a252fc06d..e0298b4fe 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -20,43 +20,19 @@ class SyncpointManager; | |||
| 20 | namespace Service::Nvidia::Devices { | 20 | namespace Service::Nvidia::Devices { |
| 21 | 21 | ||
| 22 | class nvmap; | 22 | class nvmap; |
| 23 | constexpr u32 NVGPU_IOCTL_MAGIC('H'); | ||
| 24 | constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); | ||
| 25 | constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b); | ||
| 26 | |||
| 27 | class nvhost_gpu final : public nvdevice { | 23 | class nvhost_gpu final : public nvdevice { |
| 28 | public: | 24 | public: |
| 29 | explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, | 25 | explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, |
| 30 | SyncpointManager& syncpoint_manager); | 26 | SyncpointManager& syncpoint_manager); |
| 31 | ~nvhost_gpu() override; | 27 | ~nvhost_gpu() override; |
| 32 | 28 | ||
| 33 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 29 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 34 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 30 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 35 | IoctlVersion version) override; | 31 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 32 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 33 | std::vector<u8>& inline_output) override; | ||
| 36 | 34 | ||
| 37 | private: | 35 | private: |
| 38 | enum class IoctlCommand : u32_le { | ||
| 39 | IocSetNVMAPfdCommand = 0x40044801, | ||
| 40 | IocAllocGPFIFOCommand = 0x40084805, | ||
| 41 | IocSetClientDataCommand = 0x40084714, | ||
| 42 | IocGetClientDataCommand = 0x80084715, | ||
| 43 | IocZCullBind = 0xc010480b, | ||
| 44 | IocSetErrorNotifierCommand = 0xC018480C, | ||
| 45 | IocChannelSetPriorityCommand = 0x4004480D, | ||
| 46 | IocEnableCommand = 0x0000480E, | ||
| 47 | IocDisableCommand = 0x0000480F, | ||
| 48 | IocPreemptCommand = 0x00004810, | ||
| 49 | IocForceResetCommand = 0x00004811, | ||
| 50 | IocEventIdControlCommand = 0x40084812, | ||
| 51 | IocGetErrorNotificationCommand = 0xC0104817, | ||
| 52 | IocAllocGPFIFOExCommand = 0x40204818, | ||
| 53 | IocAllocGPFIFOEx2Command = 0xC020481A, | ||
| 54 | IocAllocObjCtxCommand = 0xC0104809, | ||
| 55 | IocChannelGetWaitbaseCommand = 0xC0080003, | ||
| 56 | IocChannelSetTimeoutCommand = 0x40044803, | ||
| 57 | IocChannelSetTimeslice = 0xC004481D, | ||
| 58 | }; | ||
| 59 | |||
| 60 | enum class CtxObjects : u32_le { | 36 | enum class CtxObjects : u32_le { |
| 61 | Ctx2D = 0x902D, | 37 | Ctx2D = 0x902D, |
| 62 | Ctx3D = 0xB197, | 38 | Ctx3D = 0xB197, |
| @@ -67,63 +43,63 @@ private: | |||
| 67 | }; | 43 | }; |
| 68 | 44 | ||
| 69 | struct IoctlSetNvmapFD { | 45 | struct IoctlSetNvmapFD { |
| 70 | u32_le nvmap_fd; | 46 | s32_le nvmap_fd{}; |
| 71 | }; | 47 | }; |
| 72 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | 48 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); |
| 73 | 49 | ||
| 74 | struct IoctlChannelSetTimeout { | 50 | struct IoctlChannelSetTimeout { |
| 75 | u32_le timeout; | 51 | u32_le timeout{}; |
| 76 | }; | 52 | }; |
| 77 | static_assert(sizeof(IoctlChannelSetTimeout) == 4, "IoctlChannelSetTimeout is incorrect size"); | 53 | static_assert(sizeof(IoctlChannelSetTimeout) == 4, "IoctlChannelSetTimeout is incorrect size"); |
| 78 | 54 | ||
| 79 | struct IoctlAllocGPFIFO { | 55 | struct IoctlAllocGPFIFO { |
| 80 | u32_le num_entries; | 56 | u32_le num_entries{}; |
| 81 | u32_le flags; | 57 | u32_le flags{}; |
| 82 | }; | 58 | }; |
| 83 | static_assert(sizeof(IoctlAllocGPFIFO) == 8, "IoctlAllocGPFIFO is incorrect size"); | 59 | static_assert(sizeof(IoctlAllocGPFIFO) == 8, "IoctlAllocGPFIFO is incorrect size"); |
| 84 | 60 | ||
| 85 | struct IoctlClientData { | 61 | struct IoctlClientData { |
| 86 | u64_le data; | 62 | u64_le data{}; |
| 87 | }; | 63 | }; |
| 88 | static_assert(sizeof(IoctlClientData) == 8, "IoctlClientData is incorrect size"); | 64 | static_assert(sizeof(IoctlClientData) == 8, "IoctlClientData is incorrect size"); |
| 89 | 65 | ||
| 90 | struct IoctlZCullBind { | 66 | struct IoctlZCullBind { |
| 91 | u64_le gpu_va; | 67 | u64_le gpu_va{}; |
| 92 | u32_le mode; // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf | 68 | u32_le mode{}; // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf |
| 93 | INSERT_PADDING_WORDS(1); | 69 | INSERT_PADDING_WORDS(1); |
| 94 | }; | 70 | }; |
| 95 | static_assert(sizeof(IoctlZCullBind) == 16, "IoctlZCullBind is incorrect size"); | 71 | static_assert(sizeof(IoctlZCullBind) == 16, "IoctlZCullBind is incorrect size"); |
| 96 | 72 | ||
| 97 | struct IoctlSetErrorNotifier { | 73 | struct IoctlSetErrorNotifier { |
| 98 | u64_le offset; | 74 | u64_le offset{}; |
| 99 | u64_le size; | 75 | u64_le size{}; |
| 100 | u32_le mem; // nvmap object handle | 76 | u32_le mem{}; // nvmap object handle |
| 101 | INSERT_PADDING_WORDS(1); | 77 | INSERT_PADDING_WORDS(1); |
| 102 | }; | 78 | }; |
| 103 | static_assert(sizeof(IoctlSetErrorNotifier) == 24, "IoctlSetErrorNotifier is incorrect size"); | 79 | static_assert(sizeof(IoctlSetErrorNotifier) == 24, "IoctlSetErrorNotifier is incorrect size"); |
| 104 | 80 | ||
| 105 | struct IoctlChannelSetPriority { | 81 | struct IoctlChannelSetPriority { |
| 106 | u32_le priority; | 82 | u32_le priority{}; |
| 107 | }; | 83 | }; |
| 108 | static_assert(sizeof(IoctlChannelSetPriority) == 4, | 84 | static_assert(sizeof(IoctlChannelSetPriority) == 4, |
| 109 | "IoctlChannelSetPriority is incorrect size"); | 85 | "IoctlChannelSetPriority is incorrect size"); |
| 110 | 86 | ||
| 111 | struct IoctlSetTimeslice { | 87 | struct IoctlSetTimeslice { |
| 112 | u32_le timeslice; | 88 | u32_le timeslice{}; |
| 113 | }; | 89 | }; |
| 114 | static_assert(sizeof(IoctlSetTimeslice) == 4, "IoctlSetTimeslice is incorrect size"); | 90 | static_assert(sizeof(IoctlSetTimeslice) == 4, "IoctlSetTimeslice is incorrect size"); |
| 115 | 91 | ||
| 116 | struct IoctlEventIdControl { | 92 | struct IoctlEventIdControl { |
| 117 | u32_le cmd; // 0=disable, 1=enable, 2=clear | 93 | u32_le cmd{}; // 0=disable, 1=enable, 2=clear |
| 118 | u32_le id; | 94 | u32_le id{}; |
| 119 | }; | 95 | }; |
| 120 | static_assert(sizeof(IoctlEventIdControl) == 8, "IoctlEventIdControl is incorrect size"); | 96 | static_assert(sizeof(IoctlEventIdControl) == 8, "IoctlEventIdControl is incorrect size"); |
| 121 | 97 | ||
| 122 | struct IoctlGetErrorNotification { | 98 | struct IoctlGetErrorNotification { |
| 123 | u64_le timestamp; | 99 | u64_le timestamp{}; |
| 124 | u32_le info32; | 100 | u32_le info32{}; |
| 125 | u16_le info16; | 101 | u16_le info16{}; |
| 126 | u16_le status; // always 0xFFFF | 102 | u16_le status{}; // always 0xFFFF |
| 127 | }; | 103 | }; |
| 128 | static_assert(sizeof(IoctlGetErrorNotification) == 16, | 104 | static_assert(sizeof(IoctlGetErrorNotification) == 16, |
| 129 | "IoctlGetErrorNotification is incorrect size"); | 105 | "IoctlGetErrorNotification is incorrect size"); |
| @@ -131,39 +107,39 @@ private: | |||
| 131 | static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); | 107 | static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); |
| 132 | 108 | ||
| 133 | struct IoctlAllocGpfifoEx { | 109 | struct IoctlAllocGpfifoEx { |
| 134 | u32_le num_entries; | 110 | u32_le num_entries{}; |
| 135 | u32_le flags; | 111 | u32_le flags{}; |
| 136 | u32_le unk0; | 112 | u32_le unk0{}; |
| 137 | u32_le unk1; | 113 | u32_le unk1{}; |
| 138 | u32_le unk2; | 114 | u32_le unk2{}; |
| 139 | u32_le unk3; | 115 | u32_le unk3{}; |
| 140 | u32_le unk4; | 116 | u32_le unk4{}; |
| 141 | u32_le unk5; | 117 | u32_le unk5{}; |
| 142 | }; | 118 | }; |
| 143 | static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); | 119 | static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); |
| 144 | 120 | ||
| 145 | struct IoctlAllocGpfifoEx2 { | 121 | struct IoctlAllocGpfifoEx2 { |
| 146 | u32_le num_entries; // in | 122 | u32_le num_entries{}; // in |
| 147 | u32_le flags; // in | 123 | u32_le flags{}; // in |
| 148 | u32_le unk0; // in (1 works) | 124 | u32_le unk0{}; // in (1 works) |
| 149 | Fence fence_out; // out | 125 | Fence fence_out{}; // out |
| 150 | u32_le unk1; // in | 126 | u32_le unk1{}; // in |
| 151 | u32_le unk2; // in | 127 | u32_le unk2{}; // in |
| 152 | u32_le unk3; // in | 128 | u32_le unk3{}; // in |
| 153 | }; | 129 | }; |
| 154 | static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); | 130 | static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); |
| 155 | 131 | ||
| 156 | struct IoctlAllocObjCtx { | 132 | struct IoctlAllocObjCtx { |
| 157 | u32_le class_num; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, | 133 | u32_le class_num{}; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, |
| 158 | // 0xB06F=channel_gpfifo | 134 | // 0xB06F=channel_gpfifo |
| 159 | u32_le flags; | 135 | u32_le flags{}; |
| 160 | u64_le obj_id; // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported | 136 | u64_le obj_id{}; // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported |
| 161 | }; | 137 | }; |
| 162 | static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size"); | 138 | static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size"); |
| 163 | 139 | ||
| 164 | struct IoctlSubmitGpfifo { | 140 | struct IoctlSubmitGpfifo { |
| 165 | u64_le address; // pointer to gpfifo entry structs | 141 | u64_le address{}; // pointer to gpfifo entry structs |
| 166 | u32_le num_entries; // number of fence objects being submitted | 142 | u32_le num_entries{}; // number of fence objects being submitted |
| 167 | union { | 143 | union { |
| 168 | u32_le raw; | 144 | u32_le raw; |
| 169 | BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list | 145 | BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list |
| @@ -172,7 +148,7 @@ private: | |||
| 172 | BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt | 148 | BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt |
| 173 | BitField<8, 1, u32_le> increment; // increment the returned fence | 149 | BitField<8, 1, u32_le> increment; // increment the returned fence |
| 174 | } flags; | 150 | } flags; |
| 175 | Fence fence_out; // returned new fence object for others to wait on | 151 | Fence fence_out{}; // returned new fence object for others to wait on |
| 176 | 152 | ||
| 177 | u32 AddIncrementValue() const { | 153 | u32 AddIncrementValue() const { |
| 178 | return flags.add_increment.Value() << 1; | 154 | return flags.add_increment.Value() << 1; |
| @@ -182,33 +158,34 @@ private: | |||
| 182 | "IoctlSubmitGpfifo is incorrect size"); | 158 | "IoctlSubmitGpfifo is incorrect size"); |
| 183 | 159 | ||
| 184 | struct IoctlGetWaitbase { | 160 | struct IoctlGetWaitbase { |
| 185 | u32 unknown; // seems to be ignored? Nintendo added this | 161 | u32 unknown{}; // seems to be ignored? Nintendo added this |
| 186 | u32 value; | 162 | u32 value{}; |
| 187 | }; | 163 | }; |
| 188 | static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size"); | 164 | static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size"); |
| 189 | 165 | ||
| 190 | u32_le nvmap_fd{}; | 166 | s32_le nvmap_fd{}; |
| 191 | u64_le user_data{}; | 167 | u64_le user_data{}; |
| 192 | IoctlZCullBind zcull_params{}; | 168 | IoctlZCullBind zcull_params{}; |
| 193 | u32_le channel_priority{}; | 169 | u32_le channel_priority{}; |
| 194 | u32_le channel_timeslice{}; | 170 | u32_le channel_timeslice{}; |
| 195 | 171 | ||
| 196 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | 172 | NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); |
| 197 | u32 SetClientData(const std::vector<u8>& input, std::vector<u8>& output); | 173 | NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output); |
| 198 | u32 GetClientData(const std::vector<u8>& input, std::vector<u8>& output); | 174 | NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output); |
| 199 | u32 ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); | 175 | NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); |
| 200 | u32 SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); | 176 | NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); |
| 201 | u32 SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); | 177 | NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); |
| 202 | u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); | 178 | NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); |
| 203 | u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); | 179 | NvResult AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); |
| 204 | u32 SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, | 180 | NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, |
| 205 | Tegra::CommandList&& entries); | 181 | Tegra::CommandList&& entries); |
| 206 | u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); | 182 | NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, |
| 207 | u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, | 183 | bool kickoff = false); |
| 208 | const std::vector<u8>& input2, IoctlVersion version); | 184 | NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline, |
| 209 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | 185 | std::vector<u8>& output); |
| 210 | u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); | 186 | NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); |
| 211 | u32 ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); | 187 | NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); |
| 188 | NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 212 | 189 | ||
| 213 | std::shared_ptr<nvmap> nvmap_dev; | 190 | std::shared_ptr<nvmap> nvmap_dev; |
| 214 | SyncpointManager& syncpoint_manager; | 191 | SyncpointManager& syncpoint_manager; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index b6df48360..d8735491c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -15,46 +15,58 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_de | |||
| 15 | : nvhost_nvdec_common(system, std::move(nvmap_dev)) {} | 15 | : nvhost_nvdec_common(system, std::move(nvmap_dev)) {} |
| 16 | nvhost_nvdec::~nvhost_nvdec() = default; | 16 | nvhost_nvdec::~nvhost_nvdec() = default; |
| 17 | 17 | ||
| 18 | u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 18 | NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 19 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 19 | std::vector<u8>& output) { |
| 20 | IoctlVersion version) { | 20 | switch (command.group) { |
| 21 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 21 | case 0x0: |
| 22 | command.raw, input.size(), output.size()); | 22 | switch (command.cmd) { |
| 23 | 23 | case 0x1: | |
| 24 | switch (static_cast<IoctlCommand>(command.raw)) { | 24 | return Submit(input, output); |
| 25 | case IoctlCommand::IocSetNVMAPfdCommand: | 25 | case 0x2: |
| 26 | return SetNVMAPfd(input); | 26 | return GetSyncpoint(input, output); |
| 27 | case IoctlCommand::IocSubmit: | 27 | case 0x3: |
| 28 | return Submit(input, output); | 28 | return GetWaitbase(input, output); |
| 29 | case IoctlCommand::IocGetSyncpoint: | 29 | case 0x7: |
| 30 | return GetSyncpoint(input, output); | 30 | return SetSubmitTimeout(input, output); |
| 31 | case IoctlCommand::IocGetWaitbase: | 31 | case 0x9: |
| 32 | return GetWaitbase(input, output); | 32 | return MapBuffer(input, output); |
| 33 | case IoctlCommand::IocMapBuffer: | 33 | case 0xa: { |
| 34 | case IoctlCommand::IocMapBuffer2: | 34 | if (command.length == 0x1c) { |
| 35 | case IoctlCommand::IocMapBuffer3: | 35 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); |
| 36 | case IoctlCommand::IocMapBufferEx: | 36 | Tegra::ChCommandHeaderList cmdlist(1); |
| 37 | return MapBuffer(input, output); | 37 | cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; |
| 38 | case IoctlCommand::IocUnmapBufferEx: { | 38 | system.GPU().PushCommandBuffer(cmdlist); |
| 39 | // This command is sent when the video stream has ended, flush all video contexts | 39 | } |
| 40 | // This is usually sent in the folowing order: vic, nvdec, vic. | 40 | return UnmapBuffer(input, output); |
| 41 | // Inform the GPU to clear any remaining nvdec buffers when this is detected. | 41 | } |
| 42 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); | 42 | default: |
| 43 | Tegra::ChCommandHeaderList cmdlist(1); | 43 | break; |
| 44 | cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; | 44 | } |
| 45 | system.GPU().PushCommandBuffer(cmdlist); | 45 | break; |
| 46 | [[fallthrough]]; // fallthrough to unmap buffers | 46 | case 'H': |
| 47 | }; | 47 | switch (command.cmd) { |
| 48 | case IoctlCommand::IocUnmapBuffer: | 48 | case 0x1: |
| 49 | case IoctlCommand::IocUnmapBuffer2: | 49 | return SetNVMAPfd(input); |
| 50 | case IoctlCommand::IocUnmapBuffer3: | 50 | default: |
| 51 | return UnmapBuffer(input, output); | 51 | break; |
| 52 | case IoctlCommand::IocSetSubmitTimeout: | 52 | } |
| 53 | return SetSubmitTimeout(input, output); | 53 | break; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); | 56 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 57 | return 0; | 57 | return NvResult::NotImplemented; |
| 58 | } | ||
| 59 | |||
| 60 | NvResult nvhost_nvdec::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 61 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 62 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 63 | return NvResult::NotImplemented; | ||
| 64 | } | ||
| 65 | |||
| 66 | NvResult nvhost_nvdec::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 67 | std::vector<u8>& inline_output) { | ||
| 68 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 69 | return NvResult::NotImplemented; | ||
| 58 | } | 70 | } |
| 59 | 71 | ||
| 60 | } // namespace Service::Nvidia::Devices | 72 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 102777ddd..79b8b6de1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | |||
| @@ -14,26 +14,11 @@ public: | |||
| 14 | explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 14 | explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 15 | ~nvhost_nvdec() override; | 15 | ~nvhost_nvdec() override; |
| 16 | 16 | ||
| 17 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 17 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 18 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 18 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 19 | IoctlVersion version) override; | 19 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 20 | 20 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | |
| 21 | private: | 21 | std::vector<u8>& inline_output) override; |
| 22 | enum class IoctlCommand : u32_le { | ||
| 23 | IocSetNVMAPfdCommand = 0x40044801, | ||
| 24 | IocSubmit = 0xC0400001, | ||
| 25 | IocGetSyncpoint = 0xC0080002, | ||
| 26 | IocGetWaitbase = 0xC0080003, | ||
| 27 | IocMapBuffer = 0xC01C0009, | ||
| 28 | IocMapBuffer2 = 0xC16C0009, | ||
| 29 | IocMapBuffer3 = 0xC15C0009, | ||
| 30 | IocMapBufferEx = 0xC0A40009, | ||
| 31 | IocUnmapBuffer = 0xC0A4000A, | ||
| 32 | IocUnmapBuffer2 = 0xC16C000A, | ||
| 33 | IocUnmapBufferEx = 0xC01C000A, | ||
| 34 | IocUnmapBuffer3 = 0xC15C000A, | ||
| 35 | IocSetSubmitTimeout = 0x40040007, | ||
| 36 | }; | ||
| 37 | }; | 22 | }; |
| 38 | 23 | ||
| 39 | } // namespace Service::Nvidia::Devices | 24 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 30f03f845..b49cecb42 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -36,26 +36,20 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s | |||
| 36 | } | 36 | } |
| 37 | } // Anonymous namespace | 37 | } // Anonymous namespace |
| 38 | 38 | ||
| 39 | namespace NvErrCodes { | ||
| 40 | constexpr u32 Success{}; | ||
| 41 | [[maybe_unused]] constexpr u32 OutOfMemory{static_cast<u32>(-12)}; | ||
| 42 | constexpr u32 InvalidInput{static_cast<u32>(-22)}; | ||
| 43 | } // namespace NvErrCodes | ||
| 44 | |||
| 45 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | 39 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) |
| 46 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | 40 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} |
| 47 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; | 41 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; |
| 48 | 42 | ||
| 49 | u32 nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { | 43 | NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { |
| 50 | IoctlSetNvmapFD params{}; | 44 | IoctlSetNvmapFD params{}; |
| 51 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | 45 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); |
| 52 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 46 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 53 | 47 | ||
| 54 | nvmap_fd = params.nvmap_fd; | 48 | nvmap_fd = params.nvmap_fd; |
| 55 | return 0; | 49 | return NvResult::Success; |
| 56 | } | 50 | } |
| 57 | 51 | ||
| 58 | u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { | 52 | NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { |
| 59 | IoctlSubmit params{}; | 53 | IoctlSubmit params{}; |
| 60 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | 54 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); |
| 61 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | 55 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); |
| @@ -83,12 +77,12 @@ u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& o | |||
| 83 | 77 | ||
| 84 | for (const auto& cmd_buffer : command_buffers) { | 78 | for (const auto& cmd_buffer : command_buffers) { |
| 85 | auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); | 79 | auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); |
| 86 | ASSERT_OR_EXECUTE(object, return NvErrCodes::InvalidInput;); | 80 | ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); |
| 87 | const auto map = FindBufferMap(object->dma_map_addr); | 81 | const auto map = FindBufferMap(object->dma_map_addr); |
| 88 | if (!map) { | 82 | if (!map) { |
| 89 | LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}", | 83 | LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}", |
| 90 | object->addr, object->dma_map_addr); | 84 | object->addr, object->dma_map_addr); |
| 91 | return 0; | 85 | return NvResult::Success; |
| 92 | } | 86 | } |
| 93 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); | 87 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); |
| 94 | gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), | 88 | gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), |
| @@ -105,10 +99,10 @@ u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& o | |||
| 105 | offset = WriteVectors(output, syncpt_increments, offset); | 99 | offset = WriteVectors(output, syncpt_increments, offset); |
| 106 | offset = WriteVectors(output, wait_checks, offset); | 100 | offset = WriteVectors(output, wait_checks, offset); |
| 107 | 101 | ||
| 108 | return NvErrCodes::Success; | 102 | return NvResult::Success; |
| 109 | } | 103 | } |
| 110 | 104 | ||
| 111 | u32 nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { | 105 | NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { |
| 112 | IoctlGetSyncpoint params{}; | 106 | IoctlGetSyncpoint params{}; |
| 113 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | 107 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); |
| 114 | LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); | 108 | LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); |
| @@ -118,18 +112,18 @@ u32 nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector< | |||
| 118 | params.value = 0; | 112 | params.value = 0; |
| 119 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | 113 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); |
| 120 | 114 | ||
| 121 | return NvErrCodes::Success; | 115 | return NvResult::Success; |
| 122 | } | 116 | } |
| 123 | 117 | ||
| 124 | u32 nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { | 118 | NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { |
| 125 | IoctlGetWaitbase params{}; | 119 | IoctlGetWaitbase params{}; |
| 126 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | 120 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); |
| 127 | params.value = 0; // Seems to be hard coded at 0 | 121 | params.value = 0; // Seems to be hard coded at 0 |
| 128 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | 122 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); |
| 129 | return 0; | 123 | return NvResult::Success; |
| 130 | } | 124 | } |
| 131 | 125 | ||
| 132 | u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | 126 | NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { |
| 133 | IoctlMapBuffer params{}; | 127 | IoctlMapBuffer params{}; |
| 134 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 128 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); |
| 135 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 129 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); |
| @@ -143,7 +137,7 @@ u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8> | |||
| 143 | if (!object) { | 137 | if (!object) { |
| 144 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | 138 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); |
| 145 | std::memcpy(output.data(), ¶ms, output.size()); | 139 | std::memcpy(output.data(), ¶ms, output.size()); |
| 146 | return NvErrCodes::InvalidInput; | 140 | return NvResult::InvalidState; |
| 147 | } | 141 | } |
| 148 | if (object->dma_map_addr == 0) { | 142 | if (object->dma_map_addr == 0) { |
| 149 | // NVDEC and VIC memory is in the 32-bit address space | 143 | // NVDEC and VIC memory is in the 32-bit address space |
| @@ -165,10 +159,10 @@ u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8> | |||
| 165 | std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), | 159 | std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), |
| 166 | cmd_buffer_handles.size() * sizeof(MapBufferEntry)); | 160 | cmd_buffer_handles.size() * sizeof(MapBufferEntry)); |
| 167 | 161 | ||
| 168 | return NvErrCodes::Success; | 162 | return NvResult::Success; |
| 169 | } | 163 | } |
| 170 | 164 | ||
| 171 | u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | 165 | NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { |
| 172 | IoctlMapBuffer params{}; | 166 | IoctlMapBuffer params{}; |
| 173 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 167 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); |
| 174 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 168 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); |
| @@ -181,7 +175,7 @@ u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u | |||
| 181 | if (!object) { | 175 | if (!object) { |
| 182 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | 176 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); |
| 183 | std::memcpy(output.data(), ¶ms, output.size()); | 177 | std::memcpy(output.data(), ¶ms, output.size()); |
| 184 | return NvErrCodes::InvalidInput; | 178 | return NvResult::InvalidState; |
| 185 | } | 179 | } |
| 186 | if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { | 180 | if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { |
| 187 | gpu.MemoryManager().Unmap(object->dma_map_addr, *size); | 181 | gpu.MemoryManager().Unmap(object->dma_map_addr, *size); |
| @@ -193,13 +187,14 @@ u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u | |||
| 193 | object->dma_map_addr = 0; | 187 | object->dma_map_addr = 0; |
| 194 | } | 188 | } |
| 195 | std::memset(output.data(), 0, output.size()); | 189 | std::memset(output.data(), 0, output.size()); |
| 196 | return NvErrCodes::Success; | 190 | return NvResult::Success; |
| 197 | } | 191 | } |
| 198 | 192 | ||
| 199 | u32 nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output) { | 193 | NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, |
| 194 | std::vector<u8>& output) { | ||
| 200 | std::memcpy(&submit_timeout, input.data(), input.size()); | 195 | std::memcpy(&submit_timeout, input.data(), input.size()); |
| 201 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 196 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 202 | return NvErrCodes::Success; | 197 | return NvResult::Success; |
| 203 | } | 198 | } |
| 204 | 199 | ||
| 205 | std::optional<nvhost_nvdec_common::BufferMap> nvhost_nvdec_common::FindBufferMap( | 200 | std::optional<nvhost_nvdec_common::BufferMap> nvhost_nvdec_common::FindBufferMap( |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index c249c5349..86ba3a4d1 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -18,9 +18,37 @@ public: | |||
| 18 | explicit nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 18 | explicit nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 19 | ~nvhost_nvdec_common() override; | 19 | ~nvhost_nvdec_common() override; |
| 20 | 20 | ||
| 21 | virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 21 | /** |
| 22 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 22 | * Handles an ioctl1 request. |
| 23 | IoctlVersion version) = 0; | 23 | * @param command The ioctl command id. |
| 24 | * @param input A buffer containing the input data for the ioctl. | ||
| 25 | * @param output A buffer where the output data will be written to. | ||
| 26 | * @returns The result code of the ioctl. | ||
| 27 | */ | ||
| 28 | virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, | ||
| 29 | std::vector<u8>& output) = 0; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Handles an ioctl2 request. | ||
| 33 | * @param command The ioctl command id. | ||
| 34 | * @param input A buffer containing the input data for the ioctl. | ||
| 35 | * @param inline_input A buffer containing the input data for the ioctl which has been inlined. | ||
| 36 | * @param output A buffer where the output data will be written to. | ||
| 37 | * @returns The result code of the ioctl. | ||
| 38 | */ | ||
| 39 | virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 40 | const std::vector<u8>& inline_input, std::vector<u8>& output) = 0; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Handles an ioctl3 request. | ||
| 44 | * @param command The ioctl command id. | ||
| 45 | * @param input A buffer containing the input data for the ioctl. | ||
| 46 | * @param output A buffer where the output data will be written to. | ||
| 47 | * @param inline_output A buffer where the inlined output data will be written to. | ||
| 48 | * @returns The result code of the ioctl. | ||
| 49 | */ | ||
| 50 | virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 51 | std::vector<u8>& inline_output) = 0; | ||
| 24 | 52 | ||
| 25 | protected: | 53 | protected: |
| 26 | class BufferMap final { | 54 | class BufferMap final { |
| @@ -63,102 +91,102 @@ protected: | |||
| 63 | }; | 91 | }; |
| 64 | 92 | ||
| 65 | struct IoctlSetNvmapFD { | 93 | struct IoctlSetNvmapFD { |
| 66 | u32_le nvmap_fd; | 94 | s32_le nvmap_fd{}; |
| 67 | }; | 95 | }; |
| 68 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | 96 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); |
| 69 | 97 | ||
| 70 | struct IoctlSubmitCommandBuffer { | 98 | struct IoctlSubmitCommandBuffer { |
| 71 | u32_le id; | 99 | u32_le id{}; |
| 72 | u32_le offset; | 100 | u32_le offset{}; |
| 73 | u32_le count; | 101 | u32_le count{}; |
| 74 | }; | 102 | }; |
| 75 | static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC, | 103 | static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC, |
| 76 | "IoctlSubmitCommandBuffer is incorrect size"); | 104 | "IoctlSubmitCommandBuffer is incorrect size"); |
| 77 | struct IoctlSubmit { | 105 | struct IoctlSubmit { |
| 78 | u32_le cmd_buffer_count; | 106 | u32_le cmd_buffer_count{}; |
| 79 | u32_le relocation_count; | 107 | u32_le relocation_count{}; |
| 80 | u32_le syncpoint_count; | 108 | u32_le syncpoint_count{}; |
| 81 | u32_le fence_count; | 109 | u32_le fence_count{}; |
| 82 | }; | 110 | }; |
| 83 | static_assert(sizeof(IoctlSubmit) == 0x10, "IoctlSubmit has incorrect size"); | 111 | static_assert(sizeof(IoctlSubmit) == 0x10, "IoctlSubmit has incorrect size"); |
| 84 | 112 | ||
| 85 | struct CommandBuffer { | 113 | struct CommandBuffer { |
| 86 | s32 memory_id; | 114 | s32 memory_id{}; |
| 87 | u32 offset; | 115 | u32 offset{}; |
| 88 | s32 word_count; | 116 | s32 word_count{}; |
| 89 | }; | 117 | }; |
| 90 | static_assert(sizeof(CommandBuffer) == 0xC, "CommandBuffer has incorrect size"); | 118 | static_assert(sizeof(CommandBuffer) == 0xC, "CommandBuffer has incorrect size"); |
| 91 | 119 | ||
| 92 | struct Reloc { | 120 | struct Reloc { |
| 93 | s32 cmdbuffer_memory; | 121 | s32 cmdbuffer_memory{}; |
| 94 | s32 cmdbuffer_offset; | 122 | s32 cmdbuffer_offset{}; |
| 95 | s32 target; | 123 | s32 target{}; |
| 96 | s32 target_offset; | 124 | s32 target_offset{}; |
| 97 | }; | 125 | }; |
| 98 | static_assert(sizeof(Reloc) == 0x10, "CommandBuffer has incorrect size"); | 126 | static_assert(sizeof(Reloc) == 0x10, "CommandBuffer has incorrect size"); |
| 99 | 127 | ||
| 100 | struct SyncptIncr { | 128 | struct SyncptIncr { |
| 101 | u32 id; | 129 | u32 id{}; |
| 102 | u32 increments; | 130 | u32 increments{}; |
| 103 | }; | 131 | }; |
| 104 | static_assert(sizeof(SyncptIncr) == 0x8, "CommandBuffer has incorrect size"); | 132 | static_assert(sizeof(SyncptIncr) == 0x8, "CommandBuffer has incorrect size"); |
| 105 | 133 | ||
| 106 | struct Fence { | 134 | struct Fence { |
| 107 | u32 id; | 135 | u32 id{}; |
| 108 | u32 value; | 136 | u32 value{}; |
| 109 | }; | 137 | }; |
| 110 | static_assert(sizeof(Fence) == 0x8, "CommandBuffer has incorrect size"); | 138 | static_assert(sizeof(Fence) == 0x8, "CommandBuffer has incorrect size"); |
| 111 | 139 | ||
| 112 | struct IoctlGetSyncpoint { | 140 | struct IoctlGetSyncpoint { |
| 113 | // Input | 141 | // Input |
| 114 | u32_le param; | 142 | u32_le param{}; |
| 115 | // Output | 143 | // Output |
| 116 | u32_le value; | 144 | u32_le value{}; |
| 117 | }; | 145 | }; |
| 118 | static_assert(sizeof(IoctlGetSyncpoint) == 8, "IocGetIdParams has wrong size"); | 146 | static_assert(sizeof(IoctlGetSyncpoint) == 8, "IocGetIdParams has wrong size"); |
| 119 | 147 | ||
| 120 | struct IoctlGetWaitbase { | 148 | struct IoctlGetWaitbase { |
| 121 | u32_le unknown; // seems to be ignored? Nintendo added this | 149 | u32_le unknown{}; // seems to be ignored? Nintendo added this |
| 122 | u32_le value; | 150 | u32_le value{}; |
| 123 | }; | 151 | }; |
| 124 | static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size"); | 152 | static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size"); |
| 125 | 153 | ||
| 126 | struct IoctlMapBuffer { | 154 | struct IoctlMapBuffer { |
| 127 | u32_le num_entries; | 155 | u32_le num_entries{}; |
| 128 | u32_le data_address; // Ignored by the driver. | 156 | u32_le data_address{}; // Ignored by the driver. |
| 129 | u32_le attach_host_ch_das; | 157 | u32_le attach_host_ch_das{}; |
| 130 | }; | 158 | }; |
| 131 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | 159 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); |
| 132 | 160 | ||
| 133 | struct IocGetIdParams { | 161 | struct IocGetIdParams { |
| 134 | // Input | 162 | // Input |
| 135 | u32_le param; | 163 | u32_le param{}; |
| 136 | // Output | 164 | // Output |
| 137 | u32_le value; | 165 | u32_le value{}; |
| 138 | }; | 166 | }; |
| 139 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | 167 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); |
| 140 | 168 | ||
| 141 | // Used for mapping and unmapping command buffers | 169 | // Used for mapping and unmapping command buffers |
| 142 | struct MapBufferEntry { | 170 | struct MapBufferEntry { |
| 143 | u32_le map_handle; | 171 | u32_le map_handle{}; |
| 144 | u32_le map_address; | 172 | u32_le map_address{}; |
| 145 | }; | 173 | }; |
| 146 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | 174 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); |
| 147 | 175 | ||
| 148 | /// Ioctl command implementations | 176 | /// Ioctl command implementations |
| 149 | u32 SetNVMAPfd(const std::vector<u8>& input); | 177 | NvResult SetNVMAPfd(const std::vector<u8>& input); |
| 150 | u32 Submit(const std::vector<u8>& input, std::vector<u8>& output); | 178 | NvResult Submit(const std::vector<u8>& input, std::vector<u8>& output); |
| 151 | u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); | 179 | NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); |
| 152 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | 180 | NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); |
| 153 | u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | 181 | NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); |
| 154 | u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | 182 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); |
| 155 | u32 SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); | 183 | NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); |
| 156 | 184 | ||
| 157 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; | 185 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; |
| 158 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); | 186 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); |
| 159 | std::optional<std::size_t> RemoveBufferMap(GPUVAddr gpu_addr); | 187 | std::optional<std::size_t> RemoveBufferMap(GPUVAddr gpu_addr); |
| 160 | 188 | ||
| 161 | u32_le nvmap_fd{}; | 189 | s32_le nvmap_fd{}; |
| 162 | u32_le submit_timeout{}; | 190 | u32_le submit_timeout{}; |
| 163 | std::shared_ptr<nvmap> nvmap_dev; | 191 | std::shared_ptr<nvmap> nvmap_dev; |
| 164 | 192 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 96e7b7dab..2d06955c0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -13,28 +13,44 @@ namespace Service::Nvidia::Devices { | |||
| 13 | nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {} | 13 | nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {} |
| 14 | nvhost_nvjpg::~nvhost_nvjpg() = default; | 14 | nvhost_nvjpg::~nvhost_nvjpg() = default; |
| 15 | 15 | ||
| 16 | u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 16 | NvResult nvhost_nvjpg::Ioctl1(Ioctl command, const std::vector<u8>& input, |
| 17 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 17 | std::vector<u8>& output) { |
| 18 | IoctlVersion version) { | 18 | switch (command.group) { |
| 19 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 19 | case 'H': |
| 20 | command.raw, input.size(), output.size()); | 20 | switch (command.cmd) { |
| 21 | 21 | case 0x1: | |
| 22 | switch (static_cast<IoctlCommand>(command.raw)) { | 22 | return SetNVMAPfd(input, output); |
| 23 | case IoctlCommand::IocSetNVMAPfdCommand: | 23 | default: |
| 24 | return SetNVMAPfd(input, output); | 24 | break; |
| 25 | } | ||
| 26 | break; | ||
| 27 | default: | ||
| 28 | break; | ||
| 25 | } | 29 | } |
| 26 | 30 | ||
| 27 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 31 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 28 | return 0; | 32 | return NvResult::NotImplemented; |
| 29 | } | 33 | } |
| 30 | 34 | ||
| 31 | u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | 35 | NvResult nvhost_nvjpg::Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 36 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 37 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 38 | return NvResult::NotImplemented; | ||
| 39 | } | ||
| 40 | |||
| 41 | NvResult nvhost_nvjpg::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 42 | std::vector<u8>& inline_output) { | ||
| 43 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 44 | return NvResult::NotImplemented; | ||
| 45 | } | ||
| 46 | |||
| 47 | NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 32 | IoctlSetNvmapFD params{}; | 48 | IoctlSetNvmapFD params{}; |
| 33 | std::memcpy(¶ms, input.data(), input.size()); | 49 | std::memcpy(¶ms, input.data(), input.size()); |
| 34 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 50 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 35 | 51 | ||
| 36 | nvmap_fd = params.nvmap_fd; | 52 | nvmap_fd = params.nvmap_fd; |
| 37 | return 0; | 53 | return NvResult::Success; |
| 38 | } | 54 | } |
| 39 | 55 | ||
| 40 | } // namespace Service::Nvidia::Devices | 56 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 98dcac52f..43948d18d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | |||
| @@ -16,23 +16,21 @@ public: | |||
| 16 | explicit nvhost_nvjpg(Core::System& system); | 16 | explicit nvhost_nvjpg(Core::System& system); |
| 17 | ~nvhost_nvjpg() override; | 17 | ~nvhost_nvjpg() override; |
| 18 | 18 | ||
| 19 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 19 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 20 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 20 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 21 | IoctlVersion version) override; | 21 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 22 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 23 | std::vector<u8>& inline_output) override; | ||
| 22 | 24 | ||
| 23 | private: | 25 | private: |
| 24 | enum class IoctlCommand : u32_le { | ||
| 25 | IocSetNVMAPfdCommand = 0x40044801, | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct IoctlSetNvmapFD { | 26 | struct IoctlSetNvmapFD { |
| 29 | u32_le nvmap_fd; | 27 | s32_le nvmap_fd{}; |
| 30 | }; | 28 | }; |
| 31 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | 29 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); |
| 32 | 30 | ||
| 33 | u32_le nvmap_fd{}; | 31 | s32_le nvmap_fd{}; |
| 34 | 32 | ||
| 35 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | 33 | NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); |
| 36 | }; | 34 | }; |
| 37 | 35 | ||
| 38 | } // namespace Service::Nvidia::Devices | 36 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 60db54d00..805fe86ae 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -15,36 +15,50 @@ nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | |||
| 15 | 15 | ||
| 16 | nvhost_vic::~nvhost_vic() = default; | 16 | nvhost_vic::~nvhost_vic() = default; |
| 17 | 17 | ||
| 18 | u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 18 | NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { |
| 19 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 19 | switch (command.group) { |
| 20 | IoctlVersion version) { | 20 | case 0x0: |
| 21 | LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", | 21 | switch (command.cmd) { |
| 22 | command.raw, input.size(), output.size()); | 22 | case 0x1: |
| 23 | 23 | return Submit(input, output); | |
| 24 | switch (static_cast<IoctlCommand>(command.raw)) { | 24 | case 0x2: |
| 25 | case IoctlCommand::IocSetNVMAPfdCommand: | 25 | return GetSyncpoint(input, output); |
| 26 | return SetNVMAPfd(input); | 26 | case 0x3: |
| 27 | case IoctlCommand::IocSubmit: | 27 | return GetWaitbase(input, output); |
| 28 | return Submit(input, output); | 28 | case 0x9: |
| 29 | case IoctlCommand::IocGetSyncpoint: | 29 | return MapBuffer(input, output); |
| 30 | return GetSyncpoint(input, output); | 30 | case 0xa: |
| 31 | case IoctlCommand::IocGetWaitbase: | 31 | return UnmapBuffer(input, output); |
| 32 | return GetWaitbase(input, output); | 32 | default: |
| 33 | case IoctlCommand::IocMapBuffer: | 33 | break; |
| 34 | case IoctlCommand::IocMapBuffer2: | 34 | } |
| 35 | case IoctlCommand::IocMapBuffer3: | 35 | break; |
| 36 | case IoctlCommand::IocMapBuffer4: | 36 | case 'H': |
| 37 | case IoctlCommand::IocMapBufferEx: | 37 | switch (command.cmd) { |
| 38 | return MapBuffer(input, output); | 38 | case 0x1: |
| 39 | case IoctlCommand::IocUnmapBuffer: | 39 | return SetNVMAPfd(input); |
| 40 | case IoctlCommand::IocUnmapBuffer2: | 40 | default: |
| 41 | case IoctlCommand::IocUnmapBuffer3: | 41 | break; |
| 42 | case IoctlCommand::IocUnmapBufferEx: | 42 | } |
| 43 | return UnmapBuffer(input, output); | 43 | break; |
| 44 | default: | ||
| 45 | break; | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); | 48 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); |
| 47 | return 0; | 49 | return NvResult::NotImplemented; |
| 50 | } | ||
| 51 | |||
| 52 | NvResult nvhost_vic::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 53 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 54 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 55 | return NvResult::NotImplemented; | ||
| 56 | } | ||
| 57 | |||
| 58 | NvResult nvhost_vic::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 59 | std::vector<u8>& inline_output) { | ||
| 60 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 61 | return NvResult::NotImplemented; | ||
| 48 | } | 62 | } |
| 49 | 63 | ||
| 50 | } // namespace Service::Nvidia::Devices | 64 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index f975b190c..b2e11f4d4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -13,25 +13,11 @@ class nvhost_vic final : public nvhost_nvdec_common { | |||
| 13 | public: | 13 | public: |
| 14 | explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | 14 | explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 15 | ~nvhost_vic(); | 15 | ~nvhost_vic(); |
| 16 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | ||
| 17 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | ||
| 18 | IoctlVersion version) override; | ||
| 19 | 16 | ||
| 20 | private: | 17 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; |
| 21 | enum class IoctlCommand : u32_le { | 18 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, |
| 22 | IocSetNVMAPfdCommand = 0x40044801, | 19 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; |
| 23 | IocSubmit = 0xC0400001, | 20 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, |
| 24 | IocGetSyncpoint = 0xC0080002, | 21 | std::vector<u8>& inline_output) override; |
| 25 | IocGetWaitbase = 0xC0080003, | ||
| 26 | IocMapBuffer = 0xC01C0009, | ||
| 27 | IocMapBuffer2 = 0xC0340009, | ||
| 28 | IocMapBuffer3 = 0xC0140009, | ||
| 29 | IocMapBuffer4 = 0xC00C0009, | ||
| 30 | IocMapBufferEx = 0xC03C0009, | ||
| 31 | IocUnmapBuffer = 0xC03C000A, | ||
| 32 | IocUnmapBuffer2 = 0xC034000A, | ||
| 33 | IocUnmapBuffer3 = 0xC00C000A, | ||
| 34 | IocUnmapBufferEx = 0xC01C000A, | ||
| 35 | }; | ||
| 36 | }; | 22 | }; |
| 37 | } // namespace Service::Nvidia::Devices | 23 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 9436e16ad..4015a2740 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -11,13 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | 13 | ||
| 14 | namespace NvErrCodes { | ||
| 15 | enum { | ||
| 16 | OperationNotPermitted = -1, | ||
| 17 | InvalidValue = -22, | ||
| 18 | }; | ||
| 19 | } | ||
| 20 | |||
| 21 | nvmap::nvmap(Core::System& system) : nvdevice(system) { | 14 | nvmap::nvmap(Core::System& system) : nvdevice(system) { |
| 22 | // Handle 0 appears to be used when remapping, so we create a placeholder empty nvmap object to | 15 | // Handle 0 appears to be used when remapping, so we create a placeholder empty nvmap object to |
| 23 | // represent this. | 16 | // represent this. |
| @@ -26,6 +19,46 @@ nvmap::nvmap(Core::System& system) : nvdevice(system) { | |||
| 26 | 19 | ||
| 27 | nvmap::~nvmap() = default; | 20 | nvmap::~nvmap() = default; |
| 28 | 21 | ||
| 22 | NvResult nvmap::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 23 | switch (command.group) { | ||
| 24 | case 0x1: | ||
| 25 | switch (command.cmd) { | ||
| 26 | case 0x1: | ||
| 27 | return IocCreate(input, output); | ||
| 28 | case 0x3: | ||
| 29 | return IocFromId(input, output); | ||
| 30 | case 0x4: | ||
| 31 | return IocAlloc(input, output); | ||
| 32 | case 0x5: | ||
| 33 | return IocFree(input, output); | ||
| 34 | case 0x9: | ||
| 35 | return IocParam(input, output); | ||
| 36 | case 0xe: | ||
| 37 | return IocGetId(input, output); | ||
| 38 | default: | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | break; | ||
| 42 | default: | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | |||
| 46 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 47 | return NvResult::NotImplemented; | ||
| 48 | } | ||
| 49 | |||
| 50 | NvResult nvmap::Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 51 | const std::vector<u8>& inline_input, std::vector<u8>& output) { | ||
| 52 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 53 | return NvResult::NotImplemented; | ||
| 54 | } | ||
| 55 | |||
| 56 | NvResult nvmap::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 57 | std::vector<u8>& inline_output) { | ||
| 58 | UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); | ||
| 59 | return NvResult::NotImplemented; | ||
| 60 | } | ||
| 61 | |||
| 29 | VAddr nvmap::GetObjectAddress(u32 handle) const { | 62 | VAddr nvmap::GetObjectAddress(u32 handle) const { |
| 30 | auto object = GetObject(handle); | 63 | auto object = GetObject(handle); |
| 31 | ASSERT(object); | 64 | ASSERT(object); |
| @@ -33,28 +66,6 @@ VAddr nvmap::GetObjectAddress(u32 handle) const { | |||
| 33 | return object->addr; | 66 | return object->addr; |
| 34 | } | 67 | } |
| 35 | 68 | ||
| 36 | u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | ||
| 37 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | ||
| 38 | IoctlVersion version) { | ||
| 39 | switch (static_cast<IoctlCommand>(command.raw)) { | ||
| 40 | case IoctlCommand::Create: | ||
| 41 | return IocCreate(input, output); | ||
| 42 | case IoctlCommand::Alloc: | ||
| 43 | return IocAlloc(input, output); | ||
| 44 | case IoctlCommand::GetId: | ||
| 45 | return IocGetId(input, output); | ||
| 46 | case IoctlCommand::FromId: | ||
| 47 | return IocFromId(input, output); | ||
| 48 | case IoctlCommand::Param: | ||
| 49 | return IocParam(input, output); | ||
| 50 | case IoctlCommand::Free: | ||
| 51 | return IocFree(input, output); | ||
| 52 | } | ||
| 53 | |||
| 54 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | u32 nvmap::CreateObject(u32 size) { | 69 | u32 nvmap::CreateObject(u32 size) { |
| 59 | // Create a new nvmap object and obtain a handle to it. | 70 | // Create a new nvmap object and obtain a handle to it. |
| 60 | auto object = std::make_shared<Object>(); | 71 | auto object = std::make_shared<Object>(); |
| @@ -70,35 +81,35 @@ u32 nvmap::CreateObject(u32 size) { | |||
| 70 | return handle; | 81 | return handle; |
| 71 | } | 82 | } |
| 72 | 83 | ||
| 73 | u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { | 84 | NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { |
| 74 | IocCreateParams params; | 85 | IocCreateParams params; |
| 75 | std::memcpy(¶ms, input.data(), sizeof(params)); | 86 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 76 | LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size); | 87 | LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size); |
| 77 | 88 | ||
| 78 | if (!params.size) { | 89 | if (!params.size) { |
| 79 | LOG_ERROR(Service_NVDRV, "Size is 0"); | 90 | LOG_ERROR(Service_NVDRV, "Size is 0"); |
| 80 | return static_cast<u32>(NvErrCodes::InvalidValue); | 91 | return NvResult::BadValue; |
| 81 | } | 92 | } |
| 82 | 93 | ||
| 83 | params.handle = CreateObject(params.size); | 94 | params.handle = CreateObject(params.size); |
| 84 | 95 | ||
| 85 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 96 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 86 | return 0; | 97 | return NvResult::Success; |
| 87 | } | 98 | } |
| 88 | 99 | ||
| 89 | u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { | 100 | NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { |
| 90 | IocAllocParams params; | 101 | IocAllocParams params; |
| 91 | std::memcpy(¶ms, input.data(), sizeof(params)); | 102 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 92 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr); | 103 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr); |
| 93 | 104 | ||
| 94 | if (!params.handle) { | 105 | if (!params.handle) { |
| 95 | LOG_ERROR(Service_NVDRV, "Handle is 0"); | 106 | LOG_ERROR(Service_NVDRV, "Handle is 0"); |
| 96 | return static_cast<u32>(NvErrCodes::InvalidValue); | 107 | return NvResult::BadValue; |
| 97 | } | 108 | } |
| 98 | 109 | ||
| 99 | if ((params.align - 1) & params.align) { | 110 | if ((params.align - 1) & params.align) { |
| 100 | LOG_ERROR(Service_NVDRV, "Incorrect alignment used, alignment={:08X}", params.align); | 111 | LOG_ERROR(Service_NVDRV, "Incorrect alignment used, alignment={:08X}", params.align); |
| 101 | return static_cast<u32>(NvErrCodes::InvalidValue); | 112 | return NvResult::BadValue; |
| 102 | } | 113 | } |
| 103 | 114 | ||
| 104 | const u32 min_alignment = 0x1000; | 115 | const u32 min_alignment = 0x1000; |
| @@ -109,12 +120,12 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 109 | auto object = GetObject(params.handle); | 120 | auto object = GetObject(params.handle); |
| 110 | if (!object) { | 121 | if (!object) { |
| 111 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); | 122 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); |
| 112 | return static_cast<u32>(NvErrCodes::InvalidValue); | 123 | return NvResult::BadValue; |
| 113 | } | 124 | } |
| 114 | 125 | ||
| 115 | if (object->status == Object::Status::Allocated) { | 126 | if (object->status == Object::Status::Allocated) { |
| 116 | LOG_ERROR(Service_NVDRV, "Object is already allocated, handle={:08X}", params.handle); | 127 | LOG_ERROR(Service_NVDRV, "Object is already allocated, handle={:08X}", params.handle); |
| 117 | return static_cast<u32>(NvErrCodes::OperationNotPermitted); | 128 | return NvResult::InsufficientMemory; |
| 118 | } | 129 | } |
| 119 | 130 | ||
| 120 | object->flags = params.flags; | 131 | object->flags = params.flags; |
| @@ -124,10 +135,10 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 124 | object->status = Object::Status::Allocated; | 135 | object->status = Object::Status::Allocated; |
| 125 | 136 | ||
| 126 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 137 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 127 | return 0; | 138 | return NvResult::Success; |
| 128 | } | 139 | } |
| 129 | 140 | ||
| 130 | u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { | 141 | NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { |
| 131 | IocGetIdParams params; | 142 | IocGetIdParams params; |
| 132 | std::memcpy(¶ms, input.data(), sizeof(params)); | 143 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 133 | 144 | ||
| @@ -135,22 +146,22 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 135 | 146 | ||
| 136 | if (!params.handle) { | 147 | if (!params.handle) { |
| 137 | LOG_ERROR(Service_NVDRV, "Handle is zero"); | 148 | LOG_ERROR(Service_NVDRV, "Handle is zero"); |
| 138 | return static_cast<u32>(NvErrCodes::InvalidValue); | 149 | return NvResult::BadValue; |
| 139 | } | 150 | } |
| 140 | 151 | ||
| 141 | auto object = GetObject(params.handle); | 152 | auto object = GetObject(params.handle); |
| 142 | if (!object) { | 153 | if (!object) { |
| 143 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); | 154 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); |
| 144 | return static_cast<u32>(NvErrCodes::OperationNotPermitted); | 155 | return NvResult::BadValue; |
| 145 | } | 156 | } |
| 146 | 157 | ||
| 147 | params.id = object->id; | 158 | params.id = object->id; |
| 148 | 159 | ||
| 149 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 160 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 150 | return 0; | 161 | return NvResult::Success; |
| 151 | } | 162 | } |
| 152 | 163 | ||
| 153 | u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { | 164 | NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { |
| 154 | IocFromIdParams params; | 165 | IocFromIdParams params; |
| 155 | std::memcpy(¶ms, input.data(), sizeof(params)); | 166 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 156 | 167 | ||
| @@ -160,13 +171,13 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 160 | [&](const auto& entry) { return entry.second->id == params.id; }); | 171 | [&](const auto& entry) { return entry.second->id == params.id; }); |
| 161 | if (itr == handles.end()) { | 172 | if (itr == handles.end()) { |
| 162 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); | 173 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); |
| 163 | return static_cast<u32>(NvErrCodes::InvalidValue); | 174 | return NvResult::BadValue; |
| 164 | } | 175 | } |
| 165 | 176 | ||
| 166 | auto& object = itr->second; | 177 | auto& object = itr->second; |
| 167 | if (object->status != Object::Status::Allocated) { | 178 | if (object->status != Object::Status::Allocated) { |
| 168 | LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); | 179 | LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); |
| 169 | return static_cast<u32>(NvErrCodes::InvalidValue); | 180 | return NvResult::BadValue; |
| 170 | } | 181 | } |
| 171 | 182 | ||
| 172 | itr->second->refcount++; | 183 | itr->second->refcount++; |
| @@ -175,10 +186,10 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 175 | params.handle = itr->first; | 186 | params.handle = itr->first; |
| 176 | 187 | ||
| 177 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 188 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 178 | return 0; | 189 | return NvResult::Success; |
| 179 | } | 190 | } |
| 180 | 191 | ||
| 181 | u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | 192 | NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { |
| 182 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; | 193 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; |
| 183 | 194 | ||
| 184 | IocParamParams params; | 195 | IocParamParams params; |
| @@ -189,12 +200,12 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 189 | auto object = GetObject(params.handle); | 200 | auto object = GetObject(params.handle); |
| 190 | if (!object) { | 201 | if (!object) { |
| 191 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); | 202 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); |
| 192 | return static_cast<u32>(NvErrCodes::InvalidValue); | 203 | return NvResult::BadValue; |
| 193 | } | 204 | } |
| 194 | 205 | ||
| 195 | if (object->status != Object::Status::Allocated) { | 206 | if (object->status != Object::Status::Allocated) { |
| 196 | LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); | 207 | LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); |
| 197 | return static_cast<u32>(NvErrCodes::OperationNotPermitted); | 208 | return NvResult::BadValue; |
| 198 | } | 209 | } |
| 199 | 210 | ||
| 200 | switch (static_cast<ParamTypes>(params.param)) { | 211 | switch (static_cast<ParamTypes>(params.param)) { |
| @@ -216,10 +227,10 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 216 | } | 227 | } |
| 217 | 228 | ||
| 218 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 229 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 219 | return 0; | 230 | return NvResult::Success; |
| 220 | } | 231 | } |
| 221 | 232 | ||
| 222 | u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { | 233 | NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { |
| 223 | // TODO(Subv): These flags are unconfirmed. | 234 | // TODO(Subv): These flags are unconfirmed. |
| 224 | enum FreeFlags { | 235 | enum FreeFlags { |
| 225 | Freed = 0, | 236 | Freed = 0, |
| @@ -234,14 +245,14 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 234 | auto itr = handles.find(params.handle); | 245 | auto itr = handles.find(params.handle); |
| 235 | if (itr == handles.end()) { | 246 | if (itr == handles.end()) { |
| 236 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); | 247 | LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); |
| 237 | return static_cast<u32>(NvErrCodes::InvalidValue); | 248 | return NvResult::BadValue; |
| 238 | } | 249 | } |
| 239 | if (!itr->second->refcount) { | 250 | if (!itr->second->refcount) { |
| 240 | LOG_ERROR( | 251 | LOG_ERROR( |
| 241 | Service_NVDRV, | 252 | Service_NVDRV, |
| 242 | "There is no references to this object. The object is already freed. handle={:08X}", | 253 | "There is no references to this object. The object is already freed. handle={:08X}", |
| 243 | params.handle); | 254 | params.handle); |
| 244 | return static_cast<u32>(NvErrCodes::InvalidValue); | 255 | return NvResult::BadValue; |
| 245 | } | 256 | } |
| 246 | 257 | ||
| 247 | itr->second->refcount--; | 258 | itr->second->refcount--; |
| @@ -261,7 +272,7 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 261 | handles.erase(params.handle); | 272 | handles.erase(params.handle); |
| 262 | 273 | ||
| 263 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 274 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 264 | return 0; | 275 | return NvResult::Success; |
| 265 | } | 276 | } |
| 266 | 277 | ||
| 267 | } // namespace Service::Nvidia::Devices | 278 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 04b9ef540..4484bd79f 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -19,13 +19,15 @@ public: | |||
| 19 | explicit nvmap(Core::System& system); | 19 | explicit nvmap(Core::System& system); |
| 20 | ~nvmap() override; | 20 | ~nvmap() override; |
| 21 | 21 | ||
| 22 | NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 23 | NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, | ||
| 24 | const std::vector<u8>& inline_input, std::vector<u8>& output) override; | ||
| 25 | NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, | ||
| 26 | std::vector<u8>& inline_output) override; | ||
| 27 | |||
| 22 | /// Returns the allocated address of an nvmap object given its handle. | 28 | /// Returns the allocated address of an nvmap object given its handle. |
| 23 | VAddr GetObjectAddress(u32 handle) const; | 29 | VAddr GetObjectAddress(u32 handle) const; |
| 24 | 30 | ||
| 25 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | ||
| 26 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | ||
| 27 | IoctlVersion version) override; | ||
| 28 | |||
| 29 | /// Represents an nvmap object. | 31 | /// Represents an nvmap object. |
| 30 | struct Object { | 32 | struct Object { |
| 31 | enum class Status { Created, Allocated }; | 33 | enum class Status { Created, Allocated }; |
| @@ -58,76 +60,68 @@ private: | |||
| 58 | /// Mapping of currently allocated handles to the objects they represent. | 60 | /// Mapping of currently allocated handles to the objects they represent. |
| 59 | std::unordered_map<u32, std::shared_ptr<Object>> handles; | 61 | std::unordered_map<u32, std::shared_ptr<Object>> handles; |
| 60 | 62 | ||
| 61 | enum class IoctlCommand : u32 { | ||
| 62 | Create = 0xC0080101, | ||
| 63 | FromId = 0xC0080103, | ||
| 64 | Alloc = 0xC0200104, | ||
| 65 | Free = 0xC0180105, | ||
| 66 | Param = 0xC00C0109, | ||
| 67 | GetId = 0xC008010E, | ||
| 68 | }; | ||
| 69 | struct IocCreateParams { | 63 | struct IocCreateParams { |
| 70 | // Input | 64 | // Input |
| 71 | u32_le size; | 65 | u32_le size{}; |
| 72 | // Output | 66 | // Output |
| 73 | u32_le handle; | 67 | u32_le handle{}; |
| 74 | }; | 68 | }; |
| 75 | static_assert(sizeof(IocCreateParams) == 8, "IocCreateParams has wrong size"); | 69 | static_assert(sizeof(IocCreateParams) == 8, "IocCreateParams has wrong size"); |
| 76 | 70 | ||
| 77 | struct IocFromIdParams { | 71 | struct IocFromIdParams { |
| 78 | // Input | 72 | // Input |
| 79 | u32_le id; | 73 | u32_le id{}; |
| 80 | // Output | 74 | // Output |
| 81 | u32_le handle; | 75 | u32_le handle{}; |
| 82 | }; | 76 | }; |
| 83 | static_assert(sizeof(IocFromIdParams) == 8, "IocFromIdParams has wrong size"); | 77 | static_assert(sizeof(IocFromIdParams) == 8, "IocFromIdParams has wrong size"); |
| 84 | 78 | ||
| 85 | struct IocAllocParams { | 79 | struct IocAllocParams { |
| 86 | // Input | 80 | // Input |
| 87 | u32_le handle; | 81 | u32_le handle{}; |
| 88 | u32_le heap_mask; | 82 | u32_le heap_mask{}; |
| 89 | u32_le flags; | 83 | u32_le flags{}; |
| 90 | u32_le align; | 84 | u32_le align{}; |
| 91 | u8 kind; | 85 | u8 kind{}; |
| 92 | INSERT_PADDING_BYTES(7); | 86 | INSERT_PADDING_BYTES(7); |
| 93 | u64_le addr; | 87 | u64_le addr{}; |
| 94 | }; | 88 | }; |
| 95 | static_assert(sizeof(IocAllocParams) == 32, "IocAllocParams has wrong size"); | 89 | static_assert(sizeof(IocAllocParams) == 32, "IocAllocParams has wrong size"); |
| 96 | 90 | ||
| 97 | struct IocFreeParams { | 91 | struct IocFreeParams { |
| 98 | u32_le handle; | 92 | u32_le handle{}; |
| 99 | INSERT_PADDING_BYTES(4); | 93 | INSERT_PADDING_BYTES(4); |
| 100 | u64_le address; | 94 | u64_le address{}; |
| 101 | u32_le size; | 95 | u32_le size{}; |
| 102 | u32_le flags; | 96 | u32_le flags{}; |
| 103 | }; | 97 | }; |
| 104 | static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size"); | 98 | static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size"); |
| 105 | 99 | ||
| 106 | struct IocParamParams { | 100 | struct IocParamParams { |
| 107 | // Input | 101 | // Input |
| 108 | u32_le handle; | 102 | u32_le handle{}; |
| 109 | u32_le param; | 103 | u32_le param{}; |
| 110 | // Output | 104 | // Output |
| 111 | u32_le result; | 105 | u32_le result{}; |
| 112 | }; | 106 | }; |
| 113 | static_assert(sizeof(IocParamParams) == 12, "IocParamParams has wrong size"); | 107 | static_assert(sizeof(IocParamParams) == 12, "IocParamParams has wrong size"); |
| 114 | 108 | ||
| 115 | struct IocGetIdParams { | 109 | struct IocGetIdParams { |
| 116 | // Output | 110 | // Output |
| 117 | u32_le id; | 111 | u32_le id{}; |
| 118 | // Input | 112 | // Input |
| 119 | u32_le handle; | 113 | u32_le handle{}; |
| 120 | }; | 114 | }; |
| 121 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | 115 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); |
| 122 | 116 | ||
| 123 | u32 CreateObject(u32 size); | 117 | u32 CreateObject(u32 size); |
| 124 | 118 | ||
| 125 | u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); | 119 | NvResult IocCreate(const std::vector<u8>& input, std::vector<u8>& output); |
| 126 | u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); | 120 | NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); |
| 127 | u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); | 121 | NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output); |
| 128 | u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); | 122 | NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output); |
| 129 | u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); | 123 | NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output); |
| 130 | u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output); | 124 | NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output); |
| 131 | }; | 125 | }; |
| 132 | 126 | ||
| 133 | } // namespace Service::Nvidia::Devices | 127 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 88fbfa9b0..f6c38e853 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -23,124 +23,170 @@ void NVDRV::SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { | |||
| 23 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { | 23 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { |
| 24 | LOG_DEBUG(Service_NVDRV, "called"); | 24 | LOG_DEBUG(Service_NVDRV, "called"); |
| 25 | 25 | ||
| 26 | if (!is_initialized) { | ||
| 27 | ServiceError(ctx, NvResult::NotInitialized); | ||
| 28 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 26 | const auto& buffer = ctx.ReadBuffer(); | 32 | const auto& buffer = ctx.ReadBuffer(); |
| 27 | std::string device_name(buffer.begin(), buffer.end()); | 33 | const std::string device_name(buffer.begin(), buffer.end()); |
| 34 | DeviceFD fd = nvdrv->Open(device_name); | ||
| 28 | 35 | ||
| 29 | u32 fd = nvdrv->Open(device_name); | ||
| 30 | IPC::ResponseBuilder rb{ctx, 4}; | 36 | IPC::ResponseBuilder rb{ctx, 4}; |
| 31 | rb.Push(RESULT_SUCCESS); | 37 | rb.Push(RESULT_SUCCESS); |
| 32 | rb.Push<u32>(fd); | 38 | rb.Push<DeviceFD>(fd); |
| 33 | rb.Push<u32>(0); | 39 | rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); |
| 40 | } | ||
| 41 | |||
| 42 | void NVDRV::ServiceError(Kernel::HLERequestContext& ctx, NvResult result) { | ||
| 43 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 44 | rb.Push(RESULT_SUCCESS); | ||
| 45 | rb.PushEnum(result); | ||
| 34 | } | 46 | } |
| 35 | 47 | ||
| 36 | void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) { | 48 | void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { |
| 37 | IPC::RequestParser rp{ctx}; | 49 | IPC::RequestParser rp{ctx}; |
| 38 | u32 fd = rp.Pop<u32>(); | 50 | const auto fd = rp.Pop<DeviceFD>(); |
| 39 | u32 command = rp.Pop<u32>(); | 51 | const auto command = rp.PopRaw<Ioctl>(); |
| 40 | 52 | LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); | |
| 41 | /// Ioctl 3 has 2 outputs, first in the input params, second is the result | 53 | |
| 42 | std::vector<u8> output(ctx.GetWriteBufferSize(0)); | 54 | if (!is_initialized) { |
| 43 | std::vector<u8> output2; | 55 | ServiceError(ctx, NvResult::NotInitialized); |
| 44 | if (version == IoctlVersion::Version3) { | 56 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); |
| 45 | output2.resize((ctx.GetWriteBufferSize(1))); | 57 | return; |
| 46 | } | 58 | } |
| 47 | 59 | ||
| 48 | /// Ioctl2 has 2 inputs. It's used to pass data directly instead of providing a pointer. | 60 | // Check device |
| 49 | /// KickOfPB uses this | 61 | std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); |
| 50 | auto input = ctx.ReadBuffer(0); | 62 | const auto input_buffer = ctx.ReadBuffer(0); |
| 51 | 63 | ||
| 52 | std::vector<u8> input2; | 64 | const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer); |
| 53 | if (version == IoctlVersion::Version2) { | ||
| 54 | input2 = ctx.ReadBuffer(1); | ||
| 55 | } | ||
| 56 | 65 | ||
| 57 | IoctlCtrl ctrl{}; | 66 | if (command.is_out != 0) { |
| 58 | 67 | ctx.WriteBuffer(output_buffer); | |
| 59 | u32 result = nvdrv->Ioctl(fd, command, input, input2, output, output2, ctrl, version); | ||
| 60 | |||
| 61 | if (ctrl.must_delay) { | ||
| 62 | ctrl.fresh_call = false; | ||
| 63 | ctx.SleepClientThread( | ||
| 64 | "NVServices::DelayedResponse", ctrl.timeout, | ||
| 65 | [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_, | ||
| 66 | Kernel::ThreadWakeupReason reason) { | ||
| 67 | IoctlCtrl ctrl2{ctrl}; | ||
| 68 | std::vector<u8> tmp_output = output; | ||
| 69 | std::vector<u8> tmp_output2 = output2; | ||
| 70 | const u32 ioctl_result = nvdrv->Ioctl(fd, command, input, input2, tmp_output, | ||
| 71 | tmp_output2, ctrl2, version); | ||
| 72 | ctx_.WriteBuffer(tmp_output, 0); | ||
| 73 | if (version == IoctlVersion::Version3) { | ||
| 74 | ctx_.WriteBuffer(tmp_output2, 1); | ||
| 75 | } | ||
| 76 | IPC::ResponseBuilder rb{ctx_, 3}; | ||
| 77 | rb.Push(RESULT_SUCCESS); | ||
| 78 | rb.Push(ioctl_result); | ||
| 79 | }, | ||
| 80 | nvdrv->GetEventWriteable(ctrl.event_id)); | ||
| 81 | } else { | ||
| 82 | ctx.WriteBuffer(output); | ||
| 83 | if (version == IoctlVersion::Version3) { | ||
| 84 | ctx.WriteBuffer(output2, 1); | ||
| 85 | } | ||
| 86 | } | 68 | } |
| 69 | |||
| 87 | IPC::ResponseBuilder rb{ctx, 3}; | 70 | IPC::ResponseBuilder rb{ctx, 3}; |
| 88 | rb.Push(RESULT_SUCCESS); | 71 | rb.Push(RESULT_SUCCESS); |
| 89 | rb.Push(result); | 72 | rb.PushEnum(nv_result); |
| 90 | } | ||
| 91 | |||
| 92 | void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { | ||
| 93 | LOG_DEBUG(Service_NVDRV, "called"); | ||
| 94 | IoctlBase(ctx, IoctlVersion::Version1); | ||
| 95 | } | 73 | } |
| 96 | 74 | ||
| 97 | void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { | 75 | void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { |
| 98 | LOG_DEBUG(Service_NVDRV, "called"); | 76 | IPC::RequestParser rp{ctx}; |
| 99 | IoctlBase(ctx, IoctlVersion::Version2); | 77 | const auto fd = rp.Pop<DeviceFD>(); |
| 78 | const auto command = rp.PopRaw<Ioctl>(); | ||
| 79 | LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); | ||
| 80 | |||
| 81 | if (!is_initialized) { | ||
| 82 | ServiceError(ctx, NvResult::NotInitialized); | ||
| 83 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | const auto input_buffer = ctx.ReadBuffer(0); | ||
| 88 | const auto input_inlined_buffer = ctx.ReadBuffer(1); | ||
| 89 | std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); | ||
| 90 | |||
| 91 | const auto nv_result = | ||
| 92 | nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer); | ||
| 93 | |||
| 94 | if (command.is_out != 0) { | ||
| 95 | ctx.WriteBuffer(output_buffer); | ||
| 96 | } | ||
| 97 | |||
| 98 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 99 | rb.Push(RESULT_SUCCESS); | ||
| 100 | rb.PushEnum(nv_result); | ||
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { | 103 | void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { |
| 103 | LOG_DEBUG(Service_NVDRV, "called"); | 104 | IPC::RequestParser rp{ctx}; |
| 104 | IoctlBase(ctx, IoctlVersion::Version3); | 105 | const auto fd = rp.Pop<DeviceFD>(); |
| 106 | const auto command = rp.PopRaw<Ioctl>(); | ||
| 107 | LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); | ||
| 108 | |||
| 109 | if (!is_initialized) { | ||
| 110 | ServiceError(ctx, NvResult::NotInitialized); | ||
| 111 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | |||
| 115 | const auto input_buffer = ctx.ReadBuffer(0); | ||
| 116 | std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); | ||
| 117 | std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1)); | ||
| 118 | |||
| 119 | const auto nv_result = | ||
| 120 | nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline); | ||
| 121 | |||
| 122 | if (command.is_out != 0) { | ||
| 123 | ctx.WriteBuffer(output_buffer, 0); | ||
| 124 | ctx.WriteBuffer(output_buffer_inline, 1); | ||
| 125 | } | ||
| 126 | |||
| 127 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 128 | rb.Push(RESULT_SUCCESS); | ||
| 129 | rb.PushEnum(nv_result); | ||
| 105 | } | 130 | } |
| 106 | 131 | ||
| 107 | void NVDRV::Close(Kernel::HLERequestContext& ctx) { | 132 | void NVDRV::Close(Kernel::HLERequestContext& ctx) { |
| 108 | LOG_DEBUG(Service_NVDRV, "called"); | 133 | LOG_DEBUG(Service_NVDRV, "called"); |
| 109 | 134 | ||
| 110 | IPC::RequestParser rp{ctx}; | 135 | if (!is_initialized) { |
| 111 | u32 fd = rp.Pop<u32>(); | 136 | ServiceError(ctx, NvResult::NotInitialized); |
| 137 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | ||
| 138 | return; | ||
| 139 | } | ||
| 112 | 140 | ||
| 113 | auto result = nvdrv->Close(fd); | 141 | IPC::RequestParser rp{ctx}; |
| 142 | const auto fd = rp.Pop<DeviceFD>(); | ||
| 143 | const auto result = nvdrv->Close(fd); | ||
| 114 | 144 | ||
| 115 | IPC::ResponseBuilder rb{ctx, 2}; | 145 | IPC::ResponseBuilder rb{ctx, 3}; |
| 116 | rb.Push(result); | 146 | rb.Push(RESULT_SUCCESS); |
| 147 | rb.PushEnum(result); | ||
| 117 | } | 148 | } |
| 118 | 149 | ||
| 119 | void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { | 150 | void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { |
| 120 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 151 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 121 | 152 | ||
| 153 | is_initialized = true; | ||
| 154 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 3}; | 155 | IPC::ResponseBuilder rb{ctx, 3}; |
| 123 | rb.Push(RESULT_SUCCESS); | 156 | rb.Push(RESULT_SUCCESS); |
| 124 | rb.Push<u32>(0); | 157 | rb.PushEnum(NvResult::Success); |
| 125 | } | 158 | } |
| 126 | 159 | ||
| 127 | void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { | 160 | void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { |
| 128 | IPC::RequestParser rp{ctx}; | 161 | IPC::RequestParser rp{ctx}; |
| 129 | u32 fd = rp.Pop<u32>(); | 162 | const auto fd = rp.Pop<DeviceFD>(); |
| 130 | // TODO(Blinkhawk): Figure the meaning of the flag at bit 16 | 163 | const auto event_id = rp.Pop<u32>() & 0x00FF; |
| 131 | u32 event_id = rp.Pop<u32>() & 0x000000FF; | ||
| 132 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id); | 164 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id); |
| 133 | 165 | ||
| 134 | IPC::ResponseBuilder rb{ctx, 3, 1}; | 166 | if (!is_initialized) { |
| 135 | rb.Push(RESULT_SUCCESS); | 167 | ServiceError(ctx, NvResult::NotInitialized); |
| 168 | LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | const auto nv_result = nvdrv->VerifyFD(fd); | ||
| 173 | if (nv_result != NvResult::Success) { | ||
| 174 | LOG_ERROR(Service_NVDRV, "Invalid FD specified DeviceFD={}!", fd); | ||
| 175 | ServiceError(ctx, nv_result); | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | |||
| 136 | if (event_id < MaxNvEvents) { | 179 | if (event_id < MaxNvEvents) { |
| 180 | IPC::ResponseBuilder rb{ctx, 3, 1}; | ||
| 181 | rb.Push(RESULT_SUCCESS); | ||
| 137 | auto event = nvdrv->GetEvent(event_id); | 182 | auto event = nvdrv->GetEvent(event_id); |
| 138 | event->Clear(); | 183 | event->Clear(); |
| 139 | rb.PushCopyObjects(event); | 184 | rb.PushCopyObjects(event); |
| 140 | rb.Push<u32>(NvResult::Success); | 185 | rb.PushEnum(NvResult::Success); |
| 141 | } else { | 186 | } else { |
| 142 | rb.Push<u32>(0); | 187 | IPC::ResponseBuilder rb{ctx, 3}; |
| 143 | rb.Push<u32>(NvResult::BadParameter); | 188 | rb.Push(RESULT_SUCCESS); |
| 189 | rb.PushEnum(NvResult::BadParameter); | ||
| 144 | } | 190 | } |
| 145 | } | 191 | } |
| 146 | 192 | ||
| @@ -151,7 +197,7 @@ void NVDRV::SetAruid(Kernel::HLERequestContext& ctx) { | |||
| 151 | 197 | ||
| 152 | IPC::ResponseBuilder rb{ctx, 3}; | 198 | IPC::ResponseBuilder rb{ctx, 3}; |
| 153 | rb.Push(RESULT_SUCCESS); | 199 | rb.Push(RESULT_SUCCESS); |
| 154 | rb.Push<u32>(0); | 200 | rb.PushEnum(NvResult::Success); |
| 155 | } | 201 | } |
| 156 | 202 | ||
| 157 | void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx) { | 203 | void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx) { |
| @@ -164,8 +210,9 @@ void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ct | |||
| 164 | void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { | 210 | void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { |
| 165 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 211 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 166 | 212 | ||
| 167 | IPC::ResponseBuilder rb{ctx, 2}; | 213 | IPC::ResponseBuilder rb{ctx, 3}; |
| 168 | rb.Push(RESULT_SUCCESS); | 214 | rb.Push(RESULT_SUCCESS); |
| 215 | rb.PushEnum(NvResult::Success); | ||
| 169 | } | 216 | } |
| 170 | 217 | ||
| 171 | void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { | 218 | void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { |
| @@ -181,7 +228,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) | |||
| 181 | : ServiceFramework(name), nvdrv(std::move(nvdrv)) { | 228 | : ServiceFramework(name), nvdrv(std::move(nvdrv)) { |
| 182 | static const FunctionInfo functions[] = { | 229 | static const FunctionInfo functions[] = { |
| 183 | {0, &NVDRV::Open, "Open"}, | 230 | {0, &NVDRV::Open, "Open"}, |
| 184 | {1, &NVDRV::Ioctl, "Ioctl"}, | 231 | {1, &NVDRV::Ioctl1, "Ioctl"}, |
| 185 | {2, &NVDRV::Close, "Close"}, | 232 | {2, &NVDRV::Close, "Close"}, |
| 186 | {3, &NVDRV::Initialize, "Initialize"}, | 233 | {3, &NVDRV::Initialize, "Initialize"}, |
| 187 | {4, &NVDRV::QueryEvent, "QueryEvent"}, | 234 | {4, &NVDRV::QueryEvent, "QueryEvent"}, |
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 72e17a728..e05f905ae 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h | |||
| @@ -23,7 +23,7 @@ public: | |||
| 23 | 23 | ||
| 24 | private: | 24 | private: |
| 25 | void Open(Kernel::HLERequestContext& ctx); | 25 | void Open(Kernel::HLERequestContext& ctx); |
| 26 | void Ioctl(Kernel::HLERequestContext& ctx); | 26 | void Ioctl1(Kernel::HLERequestContext& ctx); |
| 27 | void Ioctl2(Kernel::HLERequestContext& ctx); | 27 | void Ioctl2(Kernel::HLERequestContext& ctx); |
| 28 | void Ioctl3(Kernel::HLERequestContext& ctx); | 28 | void Ioctl3(Kernel::HLERequestContext& ctx); |
| 29 | void Close(Kernel::HLERequestContext& ctx); | 29 | void Close(Kernel::HLERequestContext& ctx); |
| @@ -33,11 +33,13 @@ private: | |||
| 33 | void SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx); | 33 | void SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx); |
| 34 | void GetStatus(Kernel::HLERequestContext& ctx); | 34 | void GetStatus(Kernel::HLERequestContext& ctx); |
| 35 | void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx); | 35 | void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx); |
| 36 | void IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version); | 36 | |
| 37 | void ServiceError(Kernel::HLERequestContext& ctx, NvResult result); | ||
| 37 | 38 | ||
| 38 | std::shared_ptr<Module> nvdrv; | 39 | std::shared_ptr<Module> nvdrv; |
| 39 | 40 | ||
| 40 | u64 pid{}; | 41 | u64 pid{}; |
| 42 | bool is_initialized{}; | ||
| 41 | }; | 43 | }; |
| 42 | 44 | ||
| 43 | } // namespace Service::Nvidia | 45 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 529b03471..3294bc0e7 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h | |||
| @@ -1,12 +1,16 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include <array> | 3 | #include <array> |
| 4 | #include "common/bit_field.h" | ||
| 4 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 5 | 6 | ||
| 6 | namespace Service::Nvidia { | 7 | namespace Service::Nvidia { |
| 7 | 8 | ||
| 8 | constexpr u32 MaxSyncPoints = 192; | 9 | constexpr u32 MaxSyncPoints = 192; |
| 9 | constexpr u32 MaxNvEvents = 64; | 10 | constexpr u32 MaxNvEvents = 64; |
| 11 | using DeviceFD = s32; | ||
| 12 | |||
| 13 | constexpr DeviceFD INVALID_NVDRV_FD = -1; | ||
| 10 | 14 | ||
| 11 | struct Fence { | 15 | struct Fence { |
| 12 | s32 id; | 16 | s32 id; |
| @@ -20,11 +24,61 @@ struct MultiFence { | |||
| 20 | std::array<Fence, 4> fences; | 24 | std::array<Fence, 4> fences; |
| 21 | }; | 25 | }; |
| 22 | 26 | ||
| 23 | enum NvResult : u32 { | 27 | enum class NvResult : u32 { |
| 24 | Success = 0, | 28 | Success = 0x0, |
| 25 | BadParameter = 4, | 29 | NotImplemented = 0x1, |
| 26 | Timeout = 5, | 30 | NotSupported = 0x2, |
| 27 | ResourceError = 15, | 31 | NotInitialized = 0x3, |
| 32 | BadParameter = 0x4, | ||
| 33 | Timeout = 0x5, | ||
| 34 | InsufficientMemory = 0x6, | ||
| 35 | ReadOnlyAttribute = 0x7, | ||
| 36 | InvalidState = 0x8, | ||
| 37 | InvalidAddress = 0x9, | ||
| 38 | InvalidSize = 0xA, | ||
| 39 | BadValue = 0xB, | ||
| 40 | AlreadyAllocated = 0xD, | ||
| 41 | Busy = 0xE, | ||
| 42 | ResourceError = 0xF, | ||
| 43 | CountMismatch = 0x10, | ||
| 44 | OverFlow = 0x11, | ||
| 45 | InsufficientTransferMemory = 0x1000, | ||
| 46 | InsufficientVideoMemory = 0x10000, | ||
| 47 | BadSurfaceColorScheme = 0x10001, | ||
| 48 | InvalidSurface = 0x10002, | ||
| 49 | SurfaceNotSupported = 0x10003, | ||
| 50 | DispInitFailed = 0x20000, | ||
| 51 | DispAlreadyAttached = 0x20001, | ||
| 52 | DispTooManyDisplays = 0x20002, | ||
| 53 | DispNoDisplaysAttached = 0x20003, | ||
| 54 | DispModeNotSupported = 0x20004, | ||
| 55 | DispNotFound = 0x20005, | ||
| 56 | DispAttachDissallowed = 0x20006, | ||
| 57 | DispTypeNotSupported = 0x20007, | ||
| 58 | DispAuthenticationFailed = 0x20008, | ||
| 59 | DispNotAttached = 0x20009, | ||
| 60 | DispSamePwrState = 0x2000A, | ||
| 61 | DispEdidFailure = 0x2000B, | ||
| 62 | DispDsiReadAckError = 0x2000C, | ||
| 63 | DispDsiReadInvalidResp = 0x2000D, | ||
| 64 | FileWriteFailed = 0x30000, | ||
| 65 | FileReadFailed = 0x30001, | ||
| 66 | EndOfFile = 0x30002, | ||
| 67 | FileOperationFailed = 0x30003, | ||
| 68 | DirOperationFailed = 0x30004, | ||
| 69 | EndOfDirList = 0x30005, | ||
| 70 | ConfigVarNotFound = 0x30006, | ||
| 71 | InvalidConfigVar = 0x30007, | ||
| 72 | LibraryNotFound = 0x30008, | ||
| 73 | SymbolNotFound = 0x30009, | ||
| 74 | MemoryMapFailed = 0x3000A, | ||
| 75 | IoctlFailed = 0x3000F, | ||
| 76 | AccessDenied = 0x30010, | ||
| 77 | DeviceNotFound = 0x30011, | ||
| 78 | KernelDriverNotFound = 0x30012, | ||
| 79 | FileNotFound = 0x30013, | ||
| 80 | PathAlreadyExists = 0x30014, | ||
| 81 | ModuleNotPresent = 0xA000E, | ||
| 28 | }; | 82 | }; |
| 29 | 83 | ||
| 30 | enum class EventState { | 84 | enum class EventState { |
| @@ -34,21 +88,13 @@ enum class EventState { | |||
| 34 | Busy = 3, | 88 | Busy = 3, |
| 35 | }; | 89 | }; |
| 36 | 90 | ||
| 37 | enum class IoctlVersion : u32 { | 91 | union Ioctl { |
| 38 | Version1, | 92 | u32_le raw; |
| 39 | Version2, | 93 | BitField<0, 8, u32> cmd; |
| 40 | Version3, | 94 | BitField<8, 8, u32> group; |
| 41 | }; | 95 | BitField<16, 14, u32> length; |
| 42 | 96 | BitField<30, 1, u32> is_in; | |
| 43 | struct IoctlCtrl { | 97 | BitField<31, 1, u32> is_out; |
| 44 | // First call done to the servioce for services that call itself again after a call. | ||
| 45 | bool fresh_call{true}; | ||
| 46 | // Tells the Ioctl Wrapper that it must delay the IPC response and send the thread to sleep | ||
| 47 | bool must_delay{}; | ||
| 48 | // Timeout for the delay | ||
| 49 | s64 timeout{}; | ||
| 50 | // NV Event Id | ||
| 51 | s32 event_id{-1}; | ||
| 52 | }; | 98 | }; |
| 53 | 99 | ||
| 54 | } // namespace Service::Nvidia | 100 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 046a1f28c..bdbbedd0d 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -62,36 +62,101 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} { | |||
| 62 | 62 | ||
| 63 | Module::~Module() = default; | 63 | Module::~Module() = default; |
| 64 | 64 | ||
| 65 | u32 Module::Open(const std::string& device_name) { | 65 | NvResult Module::VerifyFD(DeviceFD fd) const { |
| 66 | ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}", | 66 | if (fd < 0) { |
| 67 | device_name); | 67 | LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); |
| 68 | return NvResult::InvalidState; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (open_files.find(fd) == open_files.end()) { | ||
| 72 | LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); | ||
| 73 | return NvResult::NotImplemented; | ||
| 74 | } | ||
| 75 | |||
| 76 | return NvResult::Success; | ||
| 77 | } | ||
| 78 | |||
| 79 | DeviceFD Module::Open(const std::string& device_name) { | ||
| 80 | if (devices.find(device_name) == devices.end()) { | ||
| 81 | LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name); | ||
| 82 | return INVALID_NVDRV_FD; | ||
| 83 | } | ||
| 68 | 84 | ||
| 69 | auto device = devices[device_name]; | 85 | auto device = devices[device_name]; |
| 70 | const u32 fd = next_fd++; | 86 | const DeviceFD fd = next_fd++; |
| 71 | 87 | ||
| 72 | open_files[fd] = std::move(device); | 88 | open_files[fd] = std::move(device); |
| 73 | 89 | ||
| 74 | return fd; | 90 | return fd; |
| 75 | } | 91 | } |
| 76 | 92 | ||
| 77 | u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2, | 93 | NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| 78 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 94 | std::vector<u8>& output) { |
| 79 | IoctlVersion version) { | 95 | if (fd < 0) { |
| 80 | auto itr = open_files.find(fd); | 96 | LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); |
| 81 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | 97 | return NvResult::InvalidState; |
| 98 | } | ||
| 82 | 99 | ||
| 83 | auto& device = itr->second; | 100 | const auto itr = open_files.find(fd); |
| 84 | return device->ioctl({command}, input, input2, output, output2, ctrl, version); | 101 | |
| 102 | if (itr == open_files.end()) { | ||
| 103 | LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); | ||
| 104 | return NvResult::NotImplemented; | ||
| 105 | } | ||
| 106 | |||
| 107 | return itr->second->Ioctl1(command, input, output); | ||
| 85 | } | 108 | } |
| 86 | 109 | ||
| 87 | ResultCode Module::Close(u32 fd) { | 110 | NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| 88 | auto itr = open_files.find(fd); | 111 | const std::vector<u8>& inline_input, std::vector<u8>& output) { |
| 89 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | 112 | if (fd < 0) { |
| 113 | LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); | ||
| 114 | return NvResult::InvalidState; | ||
| 115 | } | ||
| 116 | |||
| 117 | const auto itr = open_files.find(fd); | ||
| 118 | |||
| 119 | if (itr == open_files.end()) { | ||
| 120 | LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); | ||
| 121 | return NvResult::NotImplemented; | ||
| 122 | } | ||
| 123 | |||
| 124 | return itr->second->Ioctl2(command, input, inline_input, output); | ||
| 125 | } | ||
| 126 | |||
| 127 | NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | ||
| 128 | std::vector<u8>& output, std::vector<u8>& inline_output) { | ||
| 129 | if (fd < 0) { | ||
| 130 | LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); | ||
| 131 | return NvResult::InvalidState; | ||
| 132 | } | ||
| 133 | |||
| 134 | const auto itr = open_files.find(fd); | ||
| 135 | |||
| 136 | if (itr == open_files.end()) { | ||
| 137 | LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); | ||
| 138 | return NvResult::NotImplemented; | ||
| 139 | } | ||
| 140 | |||
| 141 | return itr->second->Ioctl3(command, input, output, inline_output); | ||
| 142 | } | ||
| 143 | |||
| 144 | NvResult Module::Close(DeviceFD fd) { | ||
| 145 | if (fd < 0) { | ||
| 146 | LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); | ||
| 147 | return NvResult::InvalidState; | ||
| 148 | } | ||
| 149 | |||
| 150 | const auto itr = open_files.find(fd); | ||
| 151 | |||
| 152 | if (itr == open_files.end()) { | ||
| 153 | LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); | ||
| 154 | return NvResult::NotImplemented; | ||
| 155 | } | ||
| 90 | 156 | ||
| 91 | open_files.erase(itr); | 157 | open_files.erase(itr); |
| 92 | 158 | ||
| 93 | // TODO(flerovium): return correct result code if operation failed. | 159 | return NvResult::Success; |
| 94 | return RESULT_SUCCESS; | ||
| 95 | } | 160 | } |
| 96 | 161 | ||
| 97 | void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { | 162 | void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index f3d863dac..7654bb026 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -112,14 +112,23 @@ public: | |||
| 112 | return std::static_pointer_cast<T>(itr->second); | 112 | return std::static_pointer_cast<T>(itr->second); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | NvResult VerifyFD(DeviceFD fd) const; | ||
| 116 | |||
| 115 | /// Opens a device node and returns a file descriptor to it. | 117 | /// Opens a device node and returns a file descriptor to it. |
| 116 | u32 Open(const std::string& device_name); | 118 | DeviceFD Open(const std::string& device_name); |
| 119 | |||
| 117 | /// Sends an ioctl command to the specified file descriptor. | 120 | /// Sends an ioctl command to the specified file descriptor. |
| 118 | u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2, | 121 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| 119 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 122 | std::vector<u8>& output); |
| 120 | IoctlVersion version); | 123 | |
| 124 | NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | ||
| 125 | const std::vector<u8>& inline_input, std::vector<u8>& output); | ||
| 126 | |||
| 127 | NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | ||
| 128 | std::vector<u8>& output, std::vector<u8>& inline_output); | ||
| 129 | |||
| 121 | /// Closes a device file descriptor and returns operation success. | 130 | /// Closes a device file descriptor and returns operation success. |
| 122 | ResultCode Close(u32 fd); | 131 | NvResult Close(DeviceFD fd); |
| 123 | 132 | ||
| 124 | void SignalSyncpt(const u32 syncpoint_id, const u32 value); | 133 | void SignalSyncpt(const u32 syncpoint_id, const u32 value); |
| 125 | 134 | ||
| @@ -132,10 +141,10 @@ private: | |||
| 132 | SyncpointManager syncpoint_manager; | 141 | SyncpointManager syncpoint_manager; |
| 133 | 142 | ||
| 134 | /// Id to use for the next open file descriptor. | 143 | /// Id to use for the next open file descriptor. |
| 135 | u32 next_fd = 1; | 144 | DeviceFD next_fd = 1; |
| 136 | 145 | ||
| 137 | /// Mapping of file descriptors to the devices they reference. | 146 | /// Mapping of file descriptors to the devices they reference. |
| 138 | std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; | 147 | std::unordered_map<DeviceFD, std::shared_ptr<Devices::nvdevice>> open_files; |
| 139 | 148 | ||
| 140 | /// Mapping of device node names to their implementation. | 149 | /// Mapping of device node names to their implementation. |
| 141 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | 150 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; |
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp new file mode 100644 index 000000000..aad4ca706 --- /dev/null +++ b/src/core/hle/service/olsc/olsc.cpp | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/ipc_helpers.h" | ||
| 6 | #include "core/hle/kernel/hle_ipc.h" | ||
| 7 | #include "core/hle/service/olsc/olsc.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/sm/sm.h" | ||
| 10 | |||
| 11 | namespace Service::OLSC { | ||
| 12 | |||
| 13 | class OLSC final : public ServiceFramework<OLSC> { | ||
| 14 | public: | ||
| 15 | explicit OLSC() : ServiceFramework{"olsc:u"} { | ||
| 16 | // clang-format off | ||
| 17 | static const FunctionInfo functions[] = { | ||
| 18 | {0, &OLSC::Initialize, "Initialize"}, | ||
| 19 | {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, | ||
| 20 | {13, nullptr, "GetSaveDataBackupSetting"}, | ||
| 21 | {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, | ||
| 22 | {15, nullptr, "SetCustomData"}, | ||
| 23 | {16, nullptr, "DeleteSaveDataBackupSetting"}, | ||
| 24 | {18, nullptr, "GetSaveDataBackupInfoCache"}, | ||
| 25 | {19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"}, | ||
| 26 | {22, nullptr, "DeleteSaveDataBackupAsync"}, | ||
| 27 | {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, | ||
| 28 | {26, nullptr, "DownloadSaveDataBackupAsync"}, | ||
| 29 | {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"}, | ||
| 30 | {9013, nullptr, "GetSaveDataBackupSettingForDebug"}, | ||
| 31 | {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"}, | ||
| 32 | {9015, nullptr, "SetCustomDataForDebug"}, | ||
| 33 | {9016, nullptr, "DeleteSaveDataBackupSettingForDebug"}, | ||
| 34 | {9018, nullptr, "GetSaveDataBackupInfoCacheForDebug"}, | ||
| 35 | {9019, nullptr, "UpdateSaveDataBackupInfoCacheAsyncForDebug"}, | ||
| 36 | {9022, nullptr, "DeleteSaveDataBackupAsyncForDebug"}, | ||
| 37 | {9025, nullptr, "ListDownloadableSaveDataBackupInfoAsyncForDebug"}, | ||
| 38 | {9026, nullptr, "DownloadSaveDataBackupAsyncForDebug"}, | ||
| 39 | }; | ||
| 40 | // clang-format on | ||
| 41 | |||
| 42 | RegisterHandlers(functions); | ||
| 43 | } | ||
| 44 | |||
| 45 | private: | ||
| 46 | void Initialize(Kernel::HLERequestContext& ctx) { | ||
| 47 | LOG_WARNING(Service_OLSC, "(STUBBED) called"); | ||
| 48 | |||
| 49 | initialized = true; | ||
| 50 | |||
| 51 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 52 | rb.Push(RESULT_SUCCESS); | ||
| 53 | } | ||
| 54 | |||
| 55 | void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) { | ||
| 56 | LOG_WARNING(Service_OLSC, "(STUBBED) called"); | ||
| 57 | |||
| 58 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 59 | rb.Push(RESULT_SUCCESS); | ||
| 60 | } | ||
| 61 | |||
| 62 | bool initialized{}; | ||
| 63 | }; | ||
| 64 | |||
| 65 | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||
| 66 | std::make_shared<OLSC>()->InstallAsService(service_manager); | ||
| 67 | } | ||
| 68 | |||
| 69 | } // namespace Service::OLSC | ||
diff --git a/src/core/hle/service/olsc/olsc.h b/src/core/hle/service/olsc/olsc.h new file mode 100644 index 000000000..edee4376b --- /dev/null +++ b/src/core/hle/service/olsc/olsc.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Service::SM { | ||
| 8 | class ServiceManager; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::OLSC { | ||
| 12 | |||
| 13 | /// Registers all SSL services with the specified service manager. | ||
| 14 | void InstallInterfaces(SM::ServiceManager& service_manager); | ||
| 15 | |||
| 16 | } // namespace Service::OLSC | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ba9159ee0..fb4979af2 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include "core/hle/service/ns/ns.h" | 51 | #include "core/hle/service/ns/ns.h" |
| 52 | #include "core/hle/service/nvdrv/nvdrv.h" | 52 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 53 | #include "core/hle/service/nvflinger/nvflinger.h" | 53 | #include "core/hle/service/nvflinger/nvflinger.h" |
| 54 | #include "core/hle/service/olsc/olsc.h" | ||
| 54 | #include "core/hle/service/pcie/pcie.h" | 55 | #include "core/hle/service/pcie/pcie.h" |
| 55 | #include "core/hle/service/pctl/module.h" | 56 | #include "core/hle/service/pctl/module.h" |
| 56 | #include "core/hle/service/pcv/pcv.h" | 57 | #include "core/hle/service/pcv/pcv.h" |
| @@ -187,17 +188,19 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co | |||
| 187 | return RESULT_SUCCESS; | 188 | return RESULT_SUCCESS; |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | /// Initialize ServiceManager | 191 | /// Initialize Services |
| 191 | void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { | 192 | Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) |
| 193 | : nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} { | ||
| 194 | |||
| 192 | // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it | 195 | // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it |
| 193 | // here and pass it into the respective InstallInterfaces functions. | 196 | // here and pass it into the respective InstallInterfaces functions. |
| 194 | auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system); | 197 | |
| 195 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | 198 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); |
| 196 | 199 | ||
| 197 | SM::ServiceManager::InstallInterfaces(sm, system.Kernel()); | 200 | SM::ServiceManager::InstallInterfaces(sm, system.Kernel()); |
| 198 | 201 | ||
| 199 | Account::InstallInterfaces(system); | 202 | Account::InstallInterfaces(system); |
| 200 | AM::InstallInterfaces(*sm, nv_flinger, system); | 203 | AM::InstallInterfaces(*sm, *nv_flinger, system); |
| 201 | AOC::InstallInterfaces(*sm, system); | 204 | AOC::InstallInterfaces(*sm, system); |
| 202 | APM::InstallInterfaces(system); | 205 | APM::InstallInterfaces(system); |
| 203 | Audio::InstallInterfaces(*sm, system); | 206 | Audio::InstallInterfaces(*sm, system); |
| @@ -231,6 +234,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { | |||
| 231 | NPNS::InstallInterfaces(*sm); | 234 | NPNS::InstallInterfaces(*sm); |
| 232 | NS::InstallInterfaces(*sm, system); | 235 | NS::InstallInterfaces(*sm, system); |
| 233 | Nvidia::InstallInterfaces(*sm, *nv_flinger, system); | 236 | Nvidia::InstallInterfaces(*sm, *nv_flinger, system); |
| 237 | OLSC::InstallInterfaces(*sm); | ||
| 234 | PCIe::InstallInterfaces(*sm); | 238 | PCIe::InstallInterfaces(*sm); |
| 235 | PCTL::InstallInterfaces(*sm); | 239 | PCTL::InstallInterfaces(*sm); |
| 236 | PCV::InstallInterfaces(*sm); | 240 | PCV::InstallInterfaces(*sm); |
| @@ -244,14 +248,10 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { | |||
| 244 | SSL::InstallInterfaces(*sm); | 248 | SSL::InstallInterfaces(*sm); |
| 245 | Time::InstallInterfaces(system); | 249 | Time::InstallInterfaces(system); |
| 246 | USB::InstallInterfaces(*sm); | 250 | USB::InstallInterfaces(*sm); |
| 247 | VI::InstallInterfaces(*sm, nv_flinger); | 251 | VI::InstallInterfaces(*sm, *nv_flinger); |
| 248 | WLAN::InstallInterfaces(*sm); | 252 | WLAN::InstallInterfaces(*sm); |
| 249 | |||
| 250 | LOG_DEBUG(Service, "initialized OK"); | ||
| 251 | } | 253 | } |
| 252 | 254 | ||
| 253 | /// Shutdown ServiceManager | 255 | Services::~Services() = default; |
| 254 | void Shutdown() { | 256 | |
| 255 | LOG_DEBUG(Service, "shutdown OK"); | ||
| 256 | } | ||
| 257 | } // namespace Service | 257 | } // namespace Service |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index a01ef3353..ed4792289 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -29,7 +29,11 @@ namespace Service { | |||
| 29 | 29 | ||
| 30 | namespace FileSystem { | 30 | namespace FileSystem { |
| 31 | class FileSystemController; | 31 | class FileSystemController; |
| 32 | } // namespace FileSystem | 32 | } |
| 33 | |||
| 34 | namespace NVFlinger { | ||
| 35 | class NVFlinger; | ||
| 36 | } | ||
| 33 | 37 | ||
| 34 | namespace SM { | 38 | namespace SM { |
| 35 | class ServiceManager; | 39 | class ServiceManager; |
| @@ -181,10 +185,17 @@ private: | |||
| 181 | } | 185 | } |
| 182 | }; | 186 | }; |
| 183 | 187 | ||
| 184 | /// Initialize ServiceManager | 188 | /** |
| 185 | void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); | 189 | * The purpose of this class is to own any objects that need to be shared across the other service |
| 190 | * implementations. Will be torn down when the global system instance is shutdown. | ||
| 191 | */ | ||
| 192 | class Services final { | ||
| 193 | public: | ||
| 194 | explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); | ||
| 195 | ~Services(); | ||
| 186 | 196 | ||
| 187 | /// Shutdown ServiceManager | 197 | private: |
| 188 | void Shutdown(); | 198 | std::unique_ptr<NVFlinger::NVFlinger> nv_flinger; |
| 199 | }; | ||
| 189 | 200 | ||
| 190 | } // namespace Service | 201 | } // namespace Service |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 5b0e371fe..86bd604f4 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -492,8 +492,8 @@ private: | |||
| 492 | 492 | ||
| 493 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | 493 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { |
| 494 | public: | 494 | public: |
| 495 | explicit IHOSBinderDriver(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 495 | explicit IHOSBinderDriver(NVFlinger::NVFlinger& nv_flinger) |
| 496 | : ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) { | 496 | : ServiceFramework("IHOSBinderDriver"), nv_flinger(nv_flinger) { |
| 497 | static const FunctionInfo functions[] = { | 497 | static const FunctionInfo functions[] = { |
| 498 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | 498 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, |
| 499 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | 499 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, |
| @@ -530,8 +530,8 @@ private: | |||
| 530 | LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, | 530 | LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, |
| 531 | static_cast<u32>(transaction), flags); | 531 | static_cast<u32>(transaction), flags); |
| 532 | 532 | ||
| 533 | const auto guard = nv_flinger->Lock(); | 533 | const auto guard = nv_flinger.Lock(); |
| 534 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 534 | auto& buffer_queue = nv_flinger.FindBufferQueue(id); |
| 535 | 535 | ||
| 536 | switch (transaction) { | 536 | switch (transaction) { |
| 537 | case TransactionId::Connect: { | 537 | case TransactionId::Connect: { |
| @@ -570,8 +570,8 @@ private: | |||
| 570 | [=, this](std::shared_ptr<Kernel::Thread> thread, | 570 | [=, this](std::shared_ptr<Kernel::Thread> thread, |
| 571 | Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { | 571 | Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { |
| 572 | // Repeat TransactParcel DequeueBuffer when a buffer is available | 572 | // Repeat TransactParcel DequeueBuffer when a buffer is available |
| 573 | const auto guard = nv_flinger->Lock(); | 573 | const auto guard = nv_flinger.Lock(); |
| 574 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 574 | auto& buffer_queue = nv_flinger.FindBufferQueue(id); |
| 575 | auto result = buffer_queue.DequeueBuffer(width, height); | 575 | auto result = buffer_queue.DequeueBuffer(width, height); |
| 576 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); | 576 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); |
| 577 | 577 | ||
| @@ -676,7 +676,7 @@ private: | |||
| 676 | 676 | ||
| 677 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); | 677 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); |
| 678 | 678 | ||
| 679 | const auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 679 | const auto& buffer_queue = nv_flinger.FindBufferQueue(id); |
| 680 | 680 | ||
| 681 | // TODO(Subv): Find out what this actually is. | 681 | // TODO(Subv): Find out what this actually is. |
| 682 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 682 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| @@ -684,8 +684,8 @@ private: | |||
| 684 | rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent()); | 684 | rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent()); |
| 685 | } | 685 | } |
| 686 | 686 | ||
| 687 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 687 | NVFlinger::NVFlinger& nv_flinger; |
| 688 | }; // namespace VI | 688 | }; |
| 689 | 689 | ||
| 690 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | 690 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { |
| 691 | public: | 691 | public: |
| @@ -771,7 +771,7 @@ private: | |||
| 771 | IPC::ResponseBuilder rb{ctx, 6}; | 771 | IPC::ResponseBuilder rb{ctx, 6}; |
| 772 | rb.Push(RESULT_SUCCESS); | 772 | rb.Push(RESULT_SUCCESS); |
| 773 | 773 | ||
| 774 | if (Settings::values.use_docked_mode) { | 774 | if (Settings::values.use_docked_mode.GetValue()) { |
| 775 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 775 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 776 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); | 776 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 777 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 777 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
| @@ -790,8 +790,8 @@ private: | |||
| 790 | 790 | ||
| 791 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 791 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { |
| 792 | public: | 792 | public: |
| 793 | explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 793 | explicit IManagerDisplayService(NVFlinger::NVFlinger& nv_flinger) |
| 794 | : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) { | 794 | : ServiceFramework("IManagerDisplayService"), nv_flinger(nv_flinger) { |
| 795 | // clang-format off | 795 | // clang-format off |
| 796 | static const FunctionInfo functions[] = { | 796 | static const FunctionInfo functions[] = { |
| 797 | {200, nullptr, "AllocateProcessHeapBlock"}, | 797 | {200, nullptr, "AllocateProcessHeapBlock"}, |
| @@ -893,7 +893,7 @@ private: | |||
| 893 | "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", | 893 | "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", |
| 894 | unknown, display, aruid); | 894 | unknown, display, aruid); |
| 895 | 895 | ||
| 896 | const auto layer_id = nv_flinger->CreateLayer(display); | 896 | const auto layer_id = nv_flinger.CreateLayer(display); |
| 897 | if (!layer_id) { | 897 | if (!layer_id) { |
| 898 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | 898 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); |
| 899 | IPC::ResponseBuilder rb{ctx, 2}; | 899 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -930,12 +930,12 @@ private: | |||
| 930 | rb.Push(RESULT_SUCCESS); | 930 | rb.Push(RESULT_SUCCESS); |
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 933 | NVFlinger::NVFlinger& nv_flinger; |
| 934 | }; | 934 | }; |
| 935 | 935 | ||
| 936 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | 936 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { |
| 937 | public: | 937 | public: |
| 938 | explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); | 938 | explicit IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger); |
| 939 | 939 | ||
| 940 | private: | 940 | private: |
| 941 | enum class ConvertedScaleMode : u64 { | 941 | enum class ConvertedScaleMode : u64 { |
| @@ -1010,7 +1010,7 @@ private: | |||
| 1010 | 1010 | ||
| 1011 | ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); | 1011 | ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); |
| 1012 | 1012 | ||
| 1013 | const auto display_id = nv_flinger->OpenDisplay(name); | 1013 | const auto display_id = nv_flinger.OpenDisplay(name); |
| 1014 | if (!display_id) { | 1014 | if (!display_id) { |
| 1015 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | 1015 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); |
| 1016 | IPC::ResponseBuilder rb{ctx, 2}; | 1016 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1110,7 +1110,7 @@ private: | |||
| 1110 | 1110 | ||
| 1111 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); | 1111 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); |
| 1112 | 1112 | ||
| 1113 | const auto display_id = nv_flinger->OpenDisplay(display_name); | 1113 | const auto display_id = nv_flinger.OpenDisplay(display_name); |
| 1114 | if (!display_id) { | 1114 | if (!display_id) { |
| 1115 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | 1115 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); |
| 1116 | IPC::ResponseBuilder rb{ctx, 2}; | 1116 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1118,7 +1118,7 @@ private: | |||
| 1118 | return; | 1118 | return; |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id); | 1121 | const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id); |
| 1122 | if (!buffer_queue_id) { | 1122 | if (!buffer_queue_id) { |
| 1123 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | 1123 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); |
| 1124 | IPC::ResponseBuilder rb{ctx, 2}; | 1124 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1138,7 +1138,7 @@ private: | |||
| 1138 | 1138 | ||
| 1139 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | 1139 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); |
| 1140 | 1140 | ||
| 1141 | nv_flinger->CloseLayer(layer_id); | 1141 | nv_flinger.CloseLayer(layer_id); |
| 1142 | 1142 | ||
| 1143 | IPC::ResponseBuilder rb{ctx, 2}; | 1143 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1144 | rb.Push(RESULT_SUCCESS); | 1144 | rb.Push(RESULT_SUCCESS); |
| @@ -1154,7 +1154,7 @@ private: | |||
| 1154 | 1154 | ||
| 1155 | // TODO(Subv): What's the difference between a Stray and a Managed layer? | 1155 | // TODO(Subv): What's the difference between a Stray and a Managed layer? |
| 1156 | 1156 | ||
| 1157 | const auto layer_id = nv_flinger->CreateLayer(display_id); | 1157 | const auto layer_id = nv_flinger.CreateLayer(display_id); |
| 1158 | if (!layer_id) { | 1158 | if (!layer_id) { |
| 1159 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id); | 1159 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id); |
| 1160 | IPC::ResponseBuilder rb{ctx, 2}; | 1160 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1162,7 +1162,7 @@ private: | |||
| 1162 | return; | 1162 | return; |
| 1163 | } | 1163 | } |
| 1164 | 1164 | ||
| 1165 | const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id); | 1165 | const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id); |
| 1166 | if (!buffer_queue_id) { | 1166 | if (!buffer_queue_id) { |
| 1167 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | 1167 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); |
| 1168 | IPC::ResponseBuilder rb{ctx, 2}; | 1168 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1193,7 +1193,7 @@ private: | |||
| 1193 | 1193 | ||
| 1194 | LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); | 1194 | LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); |
| 1195 | 1195 | ||
| 1196 | const auto vsync_event = nv_flinger->FindVsyncEvent(display_id); | 1196 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); |
| 1197 | if (!vsync_event) { | 1197 | if (!vsync_event) { |
| 1198 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | 1198 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); |
| 1199 | IPC::ResponseBuilder rb{ctx, 2}; | 1199 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -1258,12 +1258,11 @@ private: | |||
| 1258 | } | 1258 | } |
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 1261 | NVFlinger::NVFlinger& nv_flinger; |
| 1262 | }; | 1262 | }; |
| 1263 | 1263 | ||
| 1264 | IApplicationDisplayService::IApplicationDisplayService( | 1264 | IApplicationDisplayService::IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger) |
| 1265 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 1265 | : ServiceFramework("IApplicationDisplayService"), nv_flinger(nv_flinger) { |
| 1266 | : ServiceFramework("IApplicationDisplayService"), nv_flinger(std::move(nv_flinger)) { | ||
| 1267 | static const FunctionInfo functions[] = { | 1266 | static const FunctionInfo functions[] = { |
| 1268 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | 1267 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, |
| 1269 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | 1268 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, |
| @@ -1304,8 +1303,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { | |||
| 1304 | return false; | 1303 | return false; |
| 1305 | } | 1304 | } |
| 1306 | 1305 | ||
| 1307 | void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, | 1306 | void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger, |
| 1308 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, | ||
| 1309 | Permission permission) { | 1307 | Permission permission) { |
| 1310 | IPC::RequestParser rp{ctx}; | 1308 | IPC::RequestParser rp{ctx}; |
| 1311 | const auto policy = rp.PopEnum<Policy>(); | 1309 | const auto policy = rp.PopEnum<Policy>(); |
| @@ -1319,11 +1317,10 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, | |||
| 1319 | 1317 | ||
| 1320 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1318 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1321 | rb.Push(RESULT_SUCCESS); | 1319 | rb.Push(RESULT_SUCCESS); |
| 1322 | rb.PushIpcInterface<IApplicationDisplayService>(std::move(nv_flinger)); | 1320 | rb.PushIpcInterface<IApplicationDisplayService>(nv_flinger); |
| 1323 | } | 1321 | } |
| 1324 | 1322 | ||
| 1325 | void InstallInterfaces(SM::ServiceManager& service_manager, | 1323 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger) { |
| 1326 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) { | ||
| 1327 | std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager); | 1324 | std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager); |
| 1328 | std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager); | 1325 | std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager); |
| 1329 | std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager); | 1326 | std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager); |
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 6b66f8b81..5229fa753 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -43,12 +43,11 @@ enum class Policy { | |||
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | namespace detail { | 45 | namespace detail { |
| 46 | void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, | 46 | void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger, |
| 47 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, Permission permission); | 47 | Permission permission); |
| 48 | } // namespace detail | 48 | } // namespace detail |
| 49 | 49 | ||
| 50 | /// Registers all VI services with the specified service manager. | 50 | /// Registers all VI services with the specified service manager. |
| 51 | void InstallInterfaces(SM::ServiceManager& service_manager, | 51 | void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger); |
| 52 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); | ||
| 53 | 52 | ||
| 54 | } // namespace Service::VI | 53 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp index 06070087f..41da3ee93 100644 --- a/src/core/hle/service/vi/vi_m.cpp +++ b/src/core/hle/service/vi/vi_m.cpp | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::VI { | 9 | namespace Service::VI { |
| 10 | 10 | ||
| 11 | VI_M::VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 11 | VI_M::VI_M(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:m"}, nv_flinger{nv_flinger} { |
| 12 | : ServiceFramework{"vi:m"}, nv_flinger{std::move(nv_flinger)} { | ||
| 13 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 14 | {2, &VI_M::GetDisplayService, "GetDisplayService"}, | 13 | {2, &VI_M::GetDisplayService, "GetDisplayService"}, |
| 15 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 14 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h index 290e06689..ee2489874 100644 --- a/src/core/hle/service/vi/vi_m.h +++ b/src/core/hle/service/vi/vi_m.h | |||
| @@ -18,13 +18,13 @@ namespace Service::VI { | |||
| 18 | 18 | ||
| 19 | class VI_M final : public ServiceFramework<VI_M> { | 19 | class VI_M final : public ServiceFramework<VI_M> { |
| 20 | public: | 20 | public: |
| 21 | explicit VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); | 21 | explicit VI_M(NVFlinger::NVFlinger& nv_flinger); |
| 22 | ~VI_M() override; | 22 | ~VI_M() override; |
| 23 | 23 | ||
| 24 | private: | 24 | private: |
| 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); | 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); |
| 26 | 26 | ||
| 27 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 27 | NVFlinger::NVFlinger& nv_flinger; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | } // namespace Service::VI | 30 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp index 57c596cc4..6acb51e2a 100644 --- a/src/core/hle/service/vi/vi_s.cpp +++ b/src/core/hle/service/vi/vi_s.cpp | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::VI { | 9 | namespace Service::VI { |
| 10 | 10 | ||
| 11 | VI_S::VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 11 | VI_S::VI_S(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:s"}, nv_flinger{nv_flinger} { |
| 12 | : ServiceFramework{"vi:s"}, nv_flinger{std::move(nv_flinger)} { | ||
| 13 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 14 | {1, &VI_S::GetDisplayService, "GetDisplayService"}, | 13 | {1, &VI_S::GetDisplayService, "GetDisplayService"}, |
| 15 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 14 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h index 47804dc0b..6790673ab 100644 --- a/src/core/hle/service/vi/vi_s.h +++ b/src/core/hle/service/vi/vi_s.h | |||
| @@ -18,13 +18,13 @@ namespace Service::VI { | |||
| 18 | 18 | ||
| 19 | class VI_S final : public ServiceFramework<VI_S> { | 19 | class VI_S final : public ServiceFramework<VI_S> { |
| 20 | public: | 20 | public: |
| 21 | explicit VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); | 21 | explicit VI_S(NVFlinger::NVFlinger& nv_flinger); |
| 22 | ~VI_S() override; | 22 | ~VI_S() override; |
| 23 | 23 | ||
| 24 | private: | 24 | private: |
| 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); | 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); |
| 26 | 26 | ||
| 27 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 27 | NVFlinger::NVFlinger& nv_flinger; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | } // namespace Service::VI | 30 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp index 6b7329345..44e00a4f6 100644 --- a/src/core/hle/service/vi/vi_u.cpp +++ b/src/core/hle/service/vi/vi_u.cpp | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::VI { | 9 | namespace Service::VI { |
| 10 | 10 | ||
| 11 | VI_U::VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 11 | VI_U::VI_U(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:u"}, nv_flinger{nv_flinger} { |
| 12 | : ServiceFramework{"vi:u"}, nv_flinger{std::move(nv_flinger)} { | ||
| 13 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 14 | {0, &VI_U::GetDisplayService, "GetDisplayService"}, | 13 | {0, &VI_U::GetDisplayService, "GetDisplayService"}, |
| 15 | {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 14 | {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h index 19bdb73b0..b59f986f0 100644 --- a/src/core/hle/service/vi/vi_u.h +++ b/src/core/hle/service/vi/vi_u.h | |||
| @@ -18,13 +18,13 @@ namespace Service::VI { | |||
| 18 | 18 | ||
| 19 | class VI_U final : public ServiceFramework<VI_U> { | 19 | class VI_U final : public ServiceFramework<VI_U> { |
| 20 | public: | 20 | public: |
| 21 | explicit VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); | 21 | explicit VI_U(NVFlinger::NVFlinger& nv_flinger); |
| 22 | ~VI_U() override; | 22 | ~VI_U() override; |
| 23 | 23 | ||
| 24 | private: | 24 | private: |
| 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); | 25 | void GetDisplayService(Kernel::HLERequestContext& ctx); |
| 26 | 26 | ||
| 27 | std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; | 27 | NVFlinger::NVFlinger& nv_flinger; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | } // namespace Service::VI | 30 | } // namespace Service::VI |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 394a1bf26..2002dc4f2 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -114,7 +114,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | if (override_update) { | 116 | if (override_update) { |
| 117 | const FileSys::PatchManager patch_manager(metadata.GetTitleID()); | 117 | const FileSys::PatchManager patch_manager( |
| 118 | metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider()); | ||
| 118 | dir = patch_manager.PatchExeFS(dir); | 119 | dir = patch_manager.PatchExeFS(dir); |
| 119 | } | 120 | } |
| 120 | 121 | ||
| @@ -160,7 +161,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect | |||
| 160 | modules.clear(); | 161 | modules.clear(); |
| 161 | const VAddr base_address{process.PageTable().GetCodeRegionStart()}; | 162 | const VAddr base_address{process.PageTable().GetCodeRegionStart()}; |
| 162 | VAddr next_load_addr{base_address}; | 163 | VAddr next_load_addr{base_address}; |
| 163 | const FileSys::PatchManager pm{metadata.GetTitleID()}; | 164 | const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), |
| 165 | system.GetContentProvider()}; | ||
| 164 | for (const auto& module : static_modules) { | 166 | for (const auto& module : static_modules) { |
| 165 | const FileSys::VirtualFile module_file{dir->GetFile(module)}; | 167 | const FileSys::VirtualFile module_file{dir->GetFile(module)}; |
| 166 | if (!module_file) { | 168 | if (!module_file) { |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 9bc3a8840..d91c15561 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/string_util.h" | 12 | #include "common/string_util.h" |
| 13 | #include "core/core.h" | ||
| 13 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 14 | #include "core/loader/deconstructed_rom_directory.h" | 15 | #include "core/loader/deconstructed_rom_directory.h" |
| 15 | #include "core/loader/elf.h" | 16 | #include "core/loader/elf.h" |
| @@ -194,15 +195,15 @@ AppLoader::~AppLoader() = default; | |||
| 194 | 195 | ||
| 195 | /** | 196 | /** |
| 196 | * Get a loader for a file with a specific type | 197 | * Get a loader for a file with a specific type |
| 197 | * @param file The file to load | 198 | * @param system The system context to use. |
| 198 | * @param type The type of the file | 199 | * @param file The file to retrieve the loader for |
| 199 | * @param file the file to retrieve the loader for | 200 | * @param type The file type |
| 200 | * @param type the file type | 201 | * @param program_index Specifies the index within the container of the program to launch. |
| 201 | * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type | 202 | * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type |
| 202 | */ | 203 | */ |
| 203 | static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileType type) { | 204 | static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file, |
| 205 | FileType type, std::size_t program_index) { | ||
| 204 | switch (type) { | 206 | switch (type) { |
| 205 | |||
| 206 | // Standard ELF file format. | 207 | // Standard ELF file format. |
| 207 | case FileType::ELF: | 208 | case FileType::ELF: |
| 208 | return std::make_unique<AppLoader_ELF>(std::move(file)); | 209 | return std::make_unique<AppLoader_ELF>(std::move(file)); |
| @@ -221,7 +222,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT | |||
| 221 | 222 | ||
| 222 | // NX XCI (nX Card Image) file format. | 223 | // NX XCI (nX Card Image) file format. |
| 223 | case FileType::XCI: | 224 | case FileType::XCI: |
| 224 | return std::make_unique<AppLoader_XCI>(std::move(file)); | 225 | return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(), |
| 226 | system.GetContentProvider(), program_index); | ||
| 225 | 227 | ||
| 226 | // NX NAX (NintendoAesXts) file format. | 228 | // NX NAX (NintendoAesXts) file format. |
| 227 | case FileType::NAX: | 229 | case FileType::NAX: |
| @@ -229,7 +231,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT | |||
| 229 | 231 | ||
| 230 | // NX NSP (Nintendo Submission Package) file format | 232 | // NX NSP (Nintendo Submission Package) file format |
| 231 | case FileType::NSP: | 233 | case FileType::NSP: |
| 232 | return std::make_unique<AppLoader_NSP>(std::move(file)); | 234 | return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(), |
| 235 | system.GetContentProvider(), program_index); | ||
| 233 | 236 | ||
| 234 | // NX KIP (Kernel Internal Process) file format | 237 | // NX KIP (Kernel Internal Process) file format |
| 235 | case FileType::KIP: | 238 | case FileType::KIP: |
| @@ -244,20 +247,22 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT | |||
| 244 | } | 247 | } |
| 245 | } | 248 | } |
| 246 | 249 | ||
| 247 | std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file) { | 250 | std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, |
| 251 | std::size_t program_index) { | ||
| 248 | FileType type = IdentifyFile(file); | 252 | FileType type = IdentifyFile(file); |
| 249 | FileType filename_type = GuessFromFilename(file->GetName()); | 253 | const FileType filename_type = GuessFromFilename(file->GetName()); |
| 250 | 254 | ||
| 251 | // Special case: 00 is either a NCA or NAX. | 255 | // Special case: 00 is either a NCA or NAX. |
| 252 | if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) { | 256 | if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) { |
| 253 | LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName()); | 257 | LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName()); |
| 254 | if (FileType::Unknown == type) | 258 | if (FileType::Unknown == type) { |
| 255 | type = filename_type; | 259 | type = filename_type; |
| 260 | } | ||
| 256 | } | 261 | } |
| 257 | 262 | ||
| 258 | LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); | 263 | LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); |
| 259 | 264 | ||
| 260 | return GetFileLoader(std::move(file), type); | 265 | return GetFileLoader(system, std::move(file), type, program_index); |
| 261 | } | 266 | } |
| 262 | 267 | ||
| 263 | } // namespace Loader | 268 | } // namespace Loader |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index ac60b097a..36e79e71d 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -290,9 +290,14 @@ protected: | |||
| 290 | 290 | ||
| 291 | /** | 291 | /** |
| 292 | * Identifies a bootable file and return a suitable loader | 292 | * Identifies a bootable file and return a suitable loader |
| 293 | * @param file The bootable file | 293 | * |
| 294 | * @return the best loader for this file | 294 | * @param system The system context. |
| 295 | * @param file The bootable file. | ||
| 296 | * @param program_index Specifies the index within the container of the program to launch. | ||
| 297 | * | ||
| 298 | * @return the best loader for this file. | ||
| 295 | */ | 299 | */ |
| 296 | std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file); | 300 | std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, |
| 301 | std::size_t program_index = 0); | ||
| 297 | 302 | ||
| 298 | } // namespace Loader | 303 | } // namespace Loader |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 497f438a1..aa85c1a29 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -149,7 +149,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S | |||
| 149 | // Apply cheats if they exist and the program has a valid title ID | 149 | // Apply cheats if they exist and the program has a valid title ID |
| 150 | if (pm) { | 150 | if (pm) { |
| 151 | system.SetCurrentProcessBuildID(nso_header.build_id); | 151 | system.SetCurrentProcessBuildID(nso_header.build_id); |
| 152 | const auto cheats = pm->CreateCheatList(system, nso_header.build_id); | 152 | const auto cheats = pm->CreateCheatList(nso_header.build_id); |
| 153 | if (!cheats.empty()) { | 153 | if (!cheats.empty()) { |
| 154 | system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size); | 154 | system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size); |
| 155 | } | 155 | } |
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 15e528fa8..928f64c8c 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp | |||
| @@ -21,26 +21,34 @@ | |||
| 21 | 21 | ||
| 22 | namespace Loader { | 22 | namespace Loader { |
| 23 | 23 | ||
| 24 | AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) | 24 | AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file, |
| 25 | : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)), | 25 | const Service::FileSystem::FileSystemController& fsc, |
| 26 | const FileSys::ContentProvider& content_provider, | ||
| 27 | std::size_t program_index) | ||
| 28 | : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file, program_index)), | ||
| 26 | title_id(nsp->GetProgramTitleID()) { | 29 | title_id(nsp->GetProgramTitleID()) { |
| 27 | 30 | ||
| 28 | if (nsp->GetStatus() != ResultStatus::Success) | 31 | if (nsp->GetStatus() != ResultStatus::Success) { |
| 29 | return; | 32 | return; |
| 33 | } | ||
| 30 | 34 | ||
| 31 | if (nsp->IsExtractedType()) { | 35 | if (nsp->IsExtractedType()) { |
| 32 | secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); | 36 | secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); |
| 33 | } else { | 37 | } else { |
| 34 | const auto control_nca = | 38 | const auto control_nca = |
| 35 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); | 39 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); |
| 36 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) | 40 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) { |
| 37 | return; | 41 | return; |
| 42 | } | ||
| 38 | 43 | ||
| 39 | std::tie(nacp_file, icon_file) = | 44 | std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] { |
| 40 | FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca); | 45 | const FileSys::PatchManager pm{nsp->GetProgramTitleID(), fsc, content_provider}; |
| 46 | return pm.ParseControlNCA(*control_nca); | ||
| 47 | }(); | ||
| 41 | 48 | ||
| 42 | if (title_id == 0) | 49 | if (title_id == 0) { |
| 43 | return; | 50 | return; |
| 51 | } | ||
| 44 | 52 | ||
| 45 | secondary_loader = std::make_unique<AppLoader_NCA>( | 53 | secondary_loader = std::make_unique<AppLoader_NCA>( |
| 46 | nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); | 54 | nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); |
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h index b27deb686..f0518ac47 100644 --- a/src/core/loader/nsp.h +++ b/src/core/loader/nsp.h | |||
| @@ -9,15 +9,16 @@ | |||
| 9 | #include "core/file_sys/vfs.h" | 9 | #include "core/file_sys/vfs.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace FileSys { | 12 | namespace FileSys { |
| 13 | class ContentProvider; | ||
| 17 | class NACP; | 14 | class NACP; |
| 18 | class NSP; | 15 | class NSP; |
| 19 | } // namespace FileSys | 16 | } // namespace FileSys |
| 20 | 17 | ||
| 18 | namespace Service::FileSystem { | ||
| 19 | class FileSystemController; | ||
| 20 | } | ||
| 21 | |||
| 21 | namespace Loader { | 22 | namespace Loader { |
| 22 | 23 | ||
| 23 | class AppLoader_NCA; | 24 | class AppLoader_NCA; |
| @@ -25,7 +26,10 @@ class AppLoader_NCA; | |||
| 25 | /// Loads an XCI file | 26 | /// Loads an XCI file |
| 26 | class AppLoader_NSP final : public AppLoader { | 27 | class AppLoader_NSP final : public AppLoader { |
| 27 | public: | 28 | public: |
| 28 | explicit AppLoader_NSP(FileSys::VirtualFile file); | 29 | explicit AppLoader_NSP(FileSys::VirtualFile file, |
| 30 | const Service::FileSystem::FileSystemController& fsc, | ||
| 31 | const FileSys::ContentProvider& content_provider, | ||
| 32 | std::size_t program_index); | ||
| 29 | ~AppLoader_NSP() override; | 33 | ~AppLoader_NSP() override; |
| 30 | 34 | ||
| 31 | /** | 35 | /** |
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index 25e83af0f..aaa250cea 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp | |||
| @@ -20,18 +20,25 @@ | |||
| 20 | 20 | ||
| 21 | namespace Loader { | 21 | namespace Loader { |
| 22 | 22 | ||
| 23 | AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) | 23 | AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file, |
| 24 | : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), | 24 | const Service::FileSystem::FileSystemController& fsc, |
| 25 | const FileSys::ContentProvider& content_provider, | ||
| 26 | std::size_t program_index) | ||
| 27 | : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file, program_index)), | ||
| 25 | nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { | 28 | nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { |
| 26 | if (xci->GetStatus() != ResultStatus::Success) | 29 | if (xci->GetStatus() != ResultStatus::Success) { |
| 27 | return; | 30 | return; |
| 31 | } | ||
| 28 | 32 | ||
| 29 | const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); | 33 | const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); |
| 30 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) | 34 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) { |
| 31 | return; | 35 | return; |
| 36 | } | ||
| 32 | 37 | ||
| 33 | std::tie(nacp_file, icon_file) = | 38 | std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] { |
| 34 | FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(*control_nca); | 39 | const FileSys::PatchManager pm{xci->GetProgramTitleID(), fsc, content_provider}; |
| 40 | return pm.ParseControlNCA(*control_nca); | ||
| 41 | }(); | ||
| 35 | } | 42 | } |
| 36 | 43 | ||
| 37 | AppLoader_XCI::~AppLoader_XCI() = default; | 44 | AppLoader_XCI::~AppLoader_XCI() = default; |
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h index 04aea286f..764dc8328 100644 --- a/src/core/loader/xci.h +++ b/src/core/loader/xci.h | |||
| @@ -9,15 +9,16 @@ | |||
| 9 | #include "core/file_sys/vfs.h" | 9 | #include "core/file_sys/vfs.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace FileSys { | 12 | namespace FileSys { |
| 13 | class ContentProvider; | ||
| 17 | class NACP; | 14 | class NACP; |
| 18 | class XCI; | 15 | class XCI; |
| 19 | } // namespace FileSys | 16 | } // namespace FileSys |
| 20 | 17 | ||
| 18 | namespace Service::FileSystem { | ||
| 19 | class FileSystemController; | ||
| 20 | } | ||
| 21 | |||
| 21 | namespace Loader { | 22 | namespace Loader { |
| 22 | 23 | ||
| 23 | class AppLoader_NCA; | 24 | class AppLoader_NCA; |
| @@ -25,7 +26,10 @@ class AppLoader_NCA; | |||
| 25 | /// Loads an XCI file | 26 | /// Loads an XCI file |
| 26 | class AppLoader_XCI final : public AppLoader { | 27 | class AppLoader_XCI final : public AppLoader { |
| 27 | public: | 28 | public: |
| 28 | explicit AppLoader_XCI(FileSys::VirtualFile file); | 29 | explicit AppLoader_XCI(FileSys::VirtualFile file, |
| 30 | const Service::FileSystem::FileSystemController& fsc, | ||
| 31 | const FileSys::ContentProvider& content_provider, | ||
| 32 | std::size_t program_index); | ||
| 29 | ~AppLoader_XCI() override; | 33 | ~AppLoader_XCI() override; |
| 30 | 34 | ||
| 31 | /** | 35 | /** |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 0587b9374..aadbc3932 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -49,7 +49,7 @@ void LogSettings() { | |||
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | LOG_INFO(Config, "yuzu Configuration:"); | 51 | LOG_INFO(Config, "yuzu Configuration:"); |
| 52 | log_setting("Controls_UseDockedMode", values.use_docked_mode); | 52 | log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); |
| 53 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); | 53 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); |
| 54 | log_setting("System_CurrentUser", values.current_user); | 54 | log_setting("System_CurrentUser", values.current_user); |
| 55 | log_setting("System_LanguageIndex", values.language_index.GetValue()); | 55 | log_setting("System_LanguageIndex", values.language_index.GetValue()); |
| @@ -145,6 +145,12 @@ void RestoreGlobalState() { | |||
| 145 | values.rng_seed.SetGlobal(true); | 145 | values.rng_seed.SetGlobal(true); |
| 146 | values.custom_rtc.SetGlobal(true); | 146 | values.custom_rtc.SetGlobal(true); |
| 147 | values.sound_index.SetGlobal(true); | 147 | values.sound_index.SetGlobal(true); |
| 148 | |||
| 149 | // Controls | ||
| 150 | values.players.SetGlobal(true); | ||
| 151 | values.use_docked_mode.SetGlobal(true); | ||
| 152 | values.vibration_enabled.SetGlobal(true); | ||
| 153 | values.motion_enabled.SetGlobal(true); | ||
| 148 | } | 154 | } |
| 149 | 155 | ||
| 150 | void Sanitize() { | 156 | void Sanitize() { |
diff --git a/src/core/settings.h b/src/core/settings.h index 28616a574..1143aba5d 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -65,6 +65,38 @@ private: | |||
| 65 | Type local{}; | 65 | Type local{}; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | /** | ||
| 69 | * The InputSetting class allows for getting a reference to either the global or local members. | ||
| 70 | * This is required as we cannot easily modify the values of user-defined types within containers | ||
| 71 | * using the SetValue() member function found in the Setting class. The primary purpose of this | ||
| 72 | * class is to store an array of 10 PlayerInput structs for both the global and local (per-game) | ||
| 73 | * setting and allows for easily accessing and modifying both settings. | ||
| 74 | */ | ||
| 75 | template <typename Type> | ||
| 76 | class InputSetting final { | ||
| 77 | public: | ||
| 78 | InputSetting() = default; | ||
| 79 | explicit InputSetting(Type val) : global{val} {} | ||
| 80 | ~InputSetting() = default; | ||
| 81 | void SetGlobal(bool to_global) { | ||
| 82 | use_global = to_global; | ||
| 83 | } | ||
| 84 | bool UsingGlobal() const { | ||
| 85 | return use_global; | ||
| 86 | } | ||
| 87 | Type& GetValue(bool need_global = false) { | ||
| 88 | if (use_global || need_global) { | ||
| 89 | return global; | ||
| 90 | } | ||
| 91 | return local; | ||
| 92 | } | ||
| 93 | |||
| 94 | private: | ||
| 95 | bool use_global = true; | ||
| 96 | Type global{}; | ||
| 97 | Type local{}; | ||
| 98 | }; | ||
| 99 | |||
| 68 | struct TouchFromButtonMap { | 100 | struct TouchFromButtonMap { |
| 69 | std::string name; | 101 | std::string name; |
| 70 | std::vector<std::string> buttons; | 102 | std::vector<std::string> buttons; |
| @@ -133,9 +165,18 @@ struct Values { | |||
| 133 | Setting<s32> sound_index; | 165 | Setting<s32> sound_index; |
| 134 | 166 | ||
| 135 | // Controls | 167 | // Controls |
| 136 | std::array<PlayerInput, 10> players; | 168 | InputSetting<std::array<PlayerInput, 10>> players; |
| 169 | |||
| 170 | Setting<bool> use_docked_mode; | ||
| 137 | 171 | ||
| 138 | bool use_docked_mode; | 172 | Setting<bool> vibration_enabled; |
| 173 | Setting<bool> enable_accurate_vibrations; | ||
| 174 | |||
| 175 | Setting<bool> motion_enabled; | ||
| 176 | std::string motion_device; | ||
| 177 | std::string udp_input_address; | ||
| 178 | u16 udp_input_port; | ||
| 179 | u8 udp_pad_index; | ||
| 139 | 180 | ||
| 140 | bool mouse_enabled; | 181 | bool mouse_enabled; |
| 141 | std::string mouse_device; | 182 | std::string mouse_device; |
| @@ -149,20 +190,15 @@ struct Values { | |||
| 149 | ButtonsRaw debug_pad_buttons; | 190 | ButtonsRaw debug_pad_buttons; |
| 150 | AnalogsRaw debug_pad_analogs; | 191 | AnalogsRaw debug_pad_analogs; |
| 151 | 192 | ||
| 152 | bool vibration_enabled; | ||
| 153 | |||
| 154 | bool motion_enabled; | ||
| 155 | std::string motion_device; | ||
| 156 | std::string touch_device; | ||
| 157 | TouchscreenInput touchscreen; | 193 | TouchscreenInput touchscreen; |
| 158 | std::atomic_bool is_device_reload_pending{true}; | 194 | |
| 159 | bool use_touch_from_button; | 195 | bool use_touch_from_button; |
| 196 | std::string touch_device; | ||
| 160 | int touch_from_button_map_index; | 197 | int touch_from_button_map_index; |
| 161 | std::string udp_input_address; | ||
| 162 | u16 udp_input_port; | ||
| 163 | u8 udp_pad_index; | ||
| 164 | std::vector<TouchFromButtonMap> touch_from_button_maps; | 198 | std::vector<TouchFromButtonMap> touch_from_button_maps; |
| 165 | 199 | ||
| 200 | std::atomic_bool is_device_reload_pending{true}; | ||
| 201 | |||
| 166 | // Data Storage | 202 | // Data Storage |
| 167 | bool use_virtual_sd; | 203 | bool use_virtual_sd; |
| 168 | bool gamecard_inserted; | 204 | bool gamecard_inserted; |
| @@ -179,6 +215,7 @@ struct Values { | |||
| 179 | bool reporting_services; | 215 | bool reporting_services; |
| 180 | bool quest_flag; | 216 | bool quest_flag; |
| 181 | bool disable_macro_jit; | 217 | bool disable_macro_jit; |
| 218 | bool extended_logging; | ||
| 182 | 219 | ||
| 183 | // Misceallaneous | 220 | // Misceallaneous |
| 184 | std::string log_filter; | 221 | std::string log_filter; |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index ebc19e18a..d11b15f38 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -147,7 +147,9 @@ TelemetrySession::~TelemetrySession() { | |||
| 147 | } | 147 | } |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | 150 | void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, |
| 151 | const Service::FileSystem::FileSystemController& fsc, | ||
| 152 | const FileSys::ContentProvider& content_provider) { | ||
| 151 | // Log one-time top-level information | 153 | // Log one-time top-level information |
| 152 | AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); | 154 | AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); |
| 153 | 155 | ||
| @@ -167,7 +169,10 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 167 | app_loader.ReadTitle(name); | 169 | app_loader.ReadTitle(name); |
| 168 | 170 | ||
| 169 | if (name.empty()) { | 171 | if (name.empty()) { |
| 170 | const auto metadata = FileSys::PatchManager(program_id).GetControlMetadata(); | 172 | const auto metadata = [&content_provider, &fsc, program_id] { |
| 173 | const FileSys::PatchManager pm{program_id, fsc, content_provider}; | ||
| 174 | return pm.GetControlMetadata(); | ||
| 175 | }(); | ||
| 171 | if (metadata.first != nullptr) { | 176 | if (metadata.first != nullptr) { |
| 172 | name = metadata.first->GetApplicationName(); | 177 | name = metadata.first->GetApplicationName(); |
| 173 | } | 178 | } |
| @@ -213,7 +218,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 213 | Settings::values.use_assembly_shaders.GetValue()); | 218 | Settings::values.use_assembly_shaders.GetValue()); |
| 214 | AddField(field_type, "Renderer_UseAsynchronousShaders", | 219 | AddField(field_type, "Renderer_UseAsynchronousShaders", |
| 215 | Settings::values.use_asynchronous_shaders.GetValue()); | 220 | Settings::values.use_asynchronous_shaders.GetValue()); |
| 216 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); | 221 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue()); |
| 217 | } | 222 | } |
| 218 | 223 | ||
| 219 | bool TelemetrySession::SubmitTestcase() { | 224 | bool TelemetrySession::SubmitTestcase() { |
diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 66789d4bd..6f3d45bea 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h | |||
| @@ -7,10 +7,18 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include "common/telemetry.h" | 8 | #include "common/telemetry.h" |
| 9 | 9 | ||
| 10 | namespace FileSys { | ||
| 11 | class ContentProvider; | ||
| 12 | } | ||
| 13 | |||
| 10 | namespace Loader { | 14 | namespace Loader { |
| 11 | class AppLoader; | 15 | class AppLoader; |
| 12 | } | 16 | } |
| 13 | 17 | ||
| 18 | namespace Service::FileSystem { | ||
| 19 | class FileSystemController; | ||
| 20 | } | ||
| 21 | |||
| 14 | namespace Core { | 22 | namespace Core { |
| 15 | 23 | ||
| 16 | /** | 24 | /** |
| @@ -40,10 +48,14 @@ public: | |||
| 40 | * - Title file format | 48 | * - Title file format |
| 41 | * - Miscellaneous settings values. | 49 | * - Miscellaneous settings values. |
| 42 | * | 50 | * |
| 43 | * @param app_loader The application loader to use to retrieve | 51 | * @param app_loader The application loader to use to retrieve |
| 44 | * title-specific information. | 52 | * title-specific information. |
| 53 | * @param fsc Filesystem controller to use to retrieve info. | ||
| 54 | * @param content_provider Content provider to use to retrieve info. | ||
| 45 | */ | 55 | */ |
| 46 | void AddInitialInfo(Loader::AppLoader& app_loader); | 56 | void AddInitialInfo(Loader::AppLoader& app_loader, |
| 57 | const Service::FileSystem::FileSystemController& fsc, | ||
| 58 | const FileSys::ContentProvider& content_provider); | ||
| 47 | 59 | ||
| 48 | /** | 60 | /** |
| 49 | * Wrapper around the Telemetry::FieldCollection::AddField method. | 61 | * Wrapper around the Telemetry::FieldCollection::AddField method. |
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 7b39a38c1..1d1b2e08a 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -31,6 +31,9 @@ add_library(input_common STATIC | |||
| 31 | 31 | ||
| 32 | if (MSVC) | 32 | if (MSVC) |
| 33 | target_compile_options(input_common PRIVATE | 33 | target_compile_options(input_common PRIVATE |
| 34 | /W4 | ||
| 35 | /WX | ||
| 36 | |||
| 34 | # 'expression' : signed/unsigned mismatch | 37 | # 'expression' : signed/unsigned mismatch |
| 35 | /we4018 | 38 | /we4018 |
| 36 | # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) | 39 | # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) |
| @@ -46,6 +49,7 @@ if (MSVC) | |||
| 46 | ) | 49 | ) |
| 47 | else() | 50 | else() |
| 48 | target_compile_options(input_common PRIVATE | 51 | target_compile_options(input_common PRIVATE |
| 52 | -Werror | ||
| 49 | -Werror=conversion | 53 | -Werror=conversion |
| 50 | -Werror=ignored-qualifiers | 54 | -Werror=ignored-qualifiers |
| 51 | -Werror=implicit-fallthrough | 55 | -Werror=implicit-fallthrough |
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp index 74744d7f3..d748c1c04 100755 --- a/src/input_common/analog_from_button.cpp +++ b/src/input_common/analog_from_button.cpp | |||
| @@ -2,6 +2,10 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <chrono> | ||
| 6 | #include <cmath> | ||
| 7 | #include <thread> | ||
| 8 | #include "common/math_util.h" | ||
| 5 | #include "input_common/analog_from_button.h" | 9 | #include "input_common/analog_from_button.h" |
| 6 | 10 | ||
| 7 | namespace InputCommon { | 11 | namespace InputCommon { |
| @@ -11,31 +15,104 @@ public: | |||
| 11 | using Button = std::unique_ptr<Input::ButtonDevice>; | 15 | using Button = std::unique_ptr<Input::ButtonDevice>; |
| 12 | 16 | ||
| 13 | Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, | 17 | Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, |
| 14 | float modifier_scale_) | 18 | float modifier_scale_, float modifier_angle_) |
| 15 | : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), | 19 | : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), |
| 16 | right(std::move(right_)), modifier(std::move(modifier_)), | 20 | right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_), |
| 17 | modifier_scale(modifier_scale_) {} | 21 | modifier_angle(modifier_angle_) { |
| 18 | 22 | update_thread = std::thread(&Analog::UpdateStatus, this); | |
| 19 | std::tuple<float, float> GetStatus() const override { | 23 | } |
| 20 | constexpr float SQRT_HALF = 0.707106781f; | ||
| 21 | int x = 0, y = 0; | ||
| 22 | 24 | ||
| 23 | if (right->GetStatus()) { | 25 | ~Analog() override { |
| 24 | ++x; | 26 | update_thread_running = false; |
| 27 | if (update_thread.joinable()) { | ||
| 28 | update_thread.join(); | ||
| 25 | } | 29 | } |
| 26 | if (left->GetStatus()) { | 30 | } |
| 27 | --x; | 31 | |
| 32 | void MoveToDirection(bool enable, float to_angle) { | ||
| 33 | if (!enable) { | ||
| 34 | return; | ||
| 28 | } | 35 | } |
| 29 | if (up->GetStatus()) { | 36 | constexpr float TAU = Common::PI * 2.0f; |
| 30 | ++y; | 37 | // Use wider angle to ease the transition. |
| 38 | constexpr float aperture = TAU * 0.15f; | ||
| 39 | const float top_limit = to_angle + aperture; | ||
| 40 | const float bottom_limit = to_angle - aperture; | ||
| 41 | |||
| 42 | if ((angle > to_angle && angle <= top_limit) || | ||
| 43 | (angle + TAU > to_angle && angle + TAU <= top_limit)) { | ||
| 44 | angle -= modifier_angle; | ||
| 45 | if (angle < 0) { | ||
| 46 | angle += TAU; | ||
| 47 | } | ||
| 48 | } else if ((angle >= bottom_limit && angle < to_angle) || | ||
| 49 | (angle - TAU >= bottom_limit && angle - TAU < to_angle)) { | ||
| 50 | angle += modifier_angle; | ||
| 51 | if (angle >= TAU) { | ||
| 52 | angle -= TAU; | ||
| 53 | } | ||
| 54 | } else { | ||
| 55 | angle = to_angle; | ||
| 31 | } | 56 | } |
| 32 | if (down->GetStatus()) { | 57 | } |
| 33 | --y; | 58 | |
| 59 | void UpdateStatus() { | ||
| 60 | while (update_thread_running) { | ||
| 61 | const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; | ||
| 62 | |||
| 63 | bool r = right->GetStatus(); | ||
| 64 | bool l = left->GetStatus(); | ||
| 65 | bool u = up->GetStatus(); | ||
| 66 | bool d = down->GetStatus(); | ||
| 67 | |||
| 68 | // Eliminate contradictory movements | ||
| 69 | if (r && l) { | ||
| 70 | r = false; | ||
| 71 | l = false; | ||
| 72 | } | ||
| 73 | if (u && d) { | ||
| 74 | u = false; | ||
| 75 | d = false; | ||
| 76 | } | ||
| 77 | |||
| 78 | // Move to the right | ||
| 79 | MoveToDirection(r && !u && !d, 0.0f); | ||
| 80 | |||
| 81 | // Move to the upper right | ||
| 82 | MoveToDirection(r && u && !d, Common::PI * 0.25f); | ||
| 83 | |||
| 84 | // Move up | ||
| 85 | MoveToDirection(u && !l && !r, Common::PI * 0.5f); | ||
| 86 | |||
| 87 | // Move to the upper left | ||
| 88 | MoveToDirection(l && u && !d, Common::PI * 0.75f); | ||
| 89 | |||
| 90 | // Move to the left | ||
| 91 | MoveToDirection(l && !u && !d, Common::PI); | ||
| 92 | |||
| 93 | // Move to the bottom left | ||
| 94 | MoveToDirection(l && !u && d, Common::PI * 1.25f); | ||
| 95 | |||
| 96 | // Move down | ||
| 97 | MoveToDirection(d && !l && !r, Common::PI * 1.5f); | ||
| 98 | |||
| 99 | // Move to the bottom right | ||
| 100 | MoveToDirection(r && !u && d, Common::PI * 1.75f); | ||
| 101 | |||
| 102 | // Move if a key is pressed | ||
| 103 | if (r || l || u || d) { | ||
| 104 | amplitude = coef; | ||
| 105 | } else { | ||
| 106 | amplitude = 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | // Delay the update rate to 100hz | ||
| 110 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); | ||
| 34 | } | 111 | } |
| 112 | } | ||
| 35 | 113 | ||
| 36 | const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; | 114 | std::tuple<float, float> GetStatus() const override { |
| 37 | return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF), | 115 | return std::make_tuple(std::cos(angle) * amplitude, std::sin(angle) * amplitude); |
| 38 | static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); | ||
| 39 | } | 116 | } |
| 40 | 117 | ||
| 41 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | 118 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |
| @@ -59,6 +136,11 @@ private: | |||
| 59 | Button right; | 136 | Button right; |
| 60 | Button modifier; | 137 | Button modifier; |
| 61 | float modifier_scale; | 138 | float modifier_scale; |
| 139 | float modifier_angle; | ||
| 140 | float angle{}; | ||
| 141 | float amplitude{}; | ||
| 142 | std::thread update_thread; | ||
| 143 | bool update_thread_running{true}; | ||
| 62 | }; | 144 | }; |
| 63 | 145 | ||
| 64 | std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { | 146 | std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { |
| @@ -69,8 +151,10 @@ std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::Para | |||
| 69 | auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); | 151 | auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); |
| 70 | auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); | 152 | auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); |
| 71 | auto modifier_scale = params.Get("modifier_scale", 0.5f); | 153 | auto modifier_scale = params.Get("modifier_scale", 0.5f); |
| 154 | auto modifier_angle = params.Get("modifier_angle", 0.035f); | ||
| 72 | return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), | 155 | return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), |
| 73 | std::move(right), std::move(modifier), modifier_scale); | 156 | std::move(right), std::move(modifier), modifier_scale, |
| 157 | modifier_angle); | ||
| 74 | } | 158 | } |
| 75 | 159 | ||
| 76 | } // namespace InputCommon | 160 | } // namespace InputCommon |
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index b912188b6..d80195c82 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -230,10 +230,8 @@ void Adapter::SendVibrations() { | |||
| 230 | vibration_changed = false; | 230 | vibration_changed = false; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { | 233 | bool Adapter::RumblePlay(std::size_t port, u8 amplitude) { |
| 234 | amplitude = std::clamp(amplitude, 0.0f, 1.0f); | 234 | pads[port].rumble_amplitude = amplitude; |
| 235 | const auto raw_amp = static_cast<u8>(amplitude * 0x8); | ||
| 236 | pads[port].rumble_amplitude = raw_amp; | ||
| 237 | 235 | ||
| 238 | return rumble_enabled; | 236 | return rumble_enabled; |
| 239 | } | 237 | } |
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h index d28dcfad3..f1256c9da 100644 --- a/src/input_common/gcadapter/gc_adapter.h +++ b/src/input_common/gcadapter/gc_adapter.h | |||
| @@ -77,8 +77,8 @@ public: | |||
| 77 | Adapter(); | 77 | Adapter(); |
| 78 | ~Adapter(); | 78 | ~Adapter(); |
| 79 | 79 | ||
| 80 | /// Request a vibration for a controlelr | 80 | /// Request a vibration for a controller |
| 81 | bool RumblePlay(std::size_t port, f32 amplitude); | 81 | bool RumblePlay(std::size_t port, u8 amplitude); |
| 82 | 82 | ||
| 83 | /// Used for polling | 83 | /// Used for polling |
| 84 | void BeginConfiguration(); | 84 | void BeginConfiguration(); |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index 6bd6f57fc..4d1052414 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -15,7 +15,7 @@ namespace InputCommon { | |||
| 15 | 15 | ||
| 16 | class GCButton final : public Input::ButtonDevice { | 16 | class GCButton final : public Input::ButtonDevice { |
| 17 | public: | 17 | public: |
| 18 | explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter) | 18 | explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter) |
| 19 | : port(port_), button(button_), gcadapter(adapter) {} | 19 | : port(port_), button(button_), gcadapter(adapter) {} |
| 20 | 20 | ||
| 21 | ~GCButton() override; | 21 | ~GCButton() override; |
| @@ -27,18 +27,10 @@ public: | |||
| 27 | return false; | 27 | return false; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 31 | const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f; | ||
| 32 | const auto new_amp = | ||
| 33 | static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f))); | ||
| 34 | |||
| 35 | return gcadapter->RumblePlay(port, new_amp); | ||
| 36 | } | ||
| 37 | |||
| 38 | private: | 30 | private: |
| 39 | const u32 port; | 31 | const u32 port; |
| 40 | const s32 button; | 32 | const s32 button; |
| 41 | GCAdapter::Adapter* gcadapter; | 33 | const GCAdapter::Adapter* gcadapter; |
| 42 | }; | 34 | }; |
| 43 | 35 | ||
| 44 | class GCAxisButton final : public Input::ButtonDevice { | 36 | class GCAxisButton final : public Input::ButtonDevice { |
| @@ -104,7 +96,6 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param | |||
| 104 | adapter.get()); | 96 | adapter.get()); |
| 105 | } | 97 | } |
| 106 | 98 | ||
| 107 | UNREACHABLE(); | ||
| 108 | return nullptr; | 99 | return nullptr; |
| 109 | } | 100 | } |
| 110 | 101 | ||
| @@ -299,4 +290,43 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { | |||
| 299 | return params; | 290 | return params; |
| 300 | } | 291 | } |
| 301 | 292 | ||
| 293 | class GCVibration final : public Input::VibrationDevice { | ||
| 294 | public: | ||
| 295 | explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter) | ||
| 296 | : port(port_), gcadapter(adapter) {} | ||
| 297 | |||
| 298 | u8 GetStatus() const override { | ||
| 299 | return gcadapter->RumblePlay(port, 0); | ||
| 300 | } | ||
| 301 | |||
| 302 | bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high, | ||
| 303 | [[maybe_unused]] f32 freq_high) const override { | ||
| 304 | const auto mean_amplitude = (amp_low + amp_high) * 0.5f; | ||
| 305 | const auto processed_amplitude = | ||
| 306 | static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); | ||
| 307 | |||
| 308 | return gcadapter->RumblePlay(port, processed_amplitude); | ||
| 309 | } | ||
| 310 | |||
| 311 | private: | ||
| 312 | const u32 port; | ||
| 313 | GCAdapter::Adapter* gcadapter; | ||
| 314 | }; | ||
| 315 | |||
| 316 | /// An vibration device factory that creates vibration devices from GC Adapter | ||
| 317 | GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) | ||
| 318 | : adapter(std::move(adapter_)) {} | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Creates a vibration device from a joystick | ||
| 322 | * @param params contains parameters for creating the device: | ||
| 323 | * - "port": the nth gcpad on the adapter | ||
| 324 | */ | ||
| 325 | std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create( | ||
| 326 | const Common::ParamPackage& params) { | ||
| 327 | const auto port = static_cast<u32>(params.Get("port", 0)); | ||
| 328 | |||
| 329 | return std::make_unique<GCVibration>(port, adapter.get()); | ||
| 330 | } | ||
| 331 | |||
| 302 | } // namespace InputCommon | 332 | } // namespace InputCommon |
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h index 0527f328f..d1271e3ea 100644 --- a/src/input_common/gcadapter/gc_poller.h +++ b/src/input_common/gcadapter/gc_poller.h | |||
| @@ -64,4 +64,15 @@ private: | |||
| 64 | bool polling = false; | 64 | bool polling = false; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /// A vibration device factory creates vibration devices from GC Adapter | ||
| 68 | class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 69 | public: | ||
| 70 | explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_); | ||
| 71 | |||
| 72 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override; | ||
| 73 | |||
| 74 | private: | ||
| 75 | std::shared_ptr<GCAdapter::Adapter> adapter; | ||
| 76 | }; | ||
| 77 | |||
| 67 | } // namespace InputCommon | 78 | } // namespace InputCommon |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index d32fd8b81..e59ad4ff5 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -28,6 +28,8 @@ struct InputSubsystem::Impl { | |||
| 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); |
| 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); |
| 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); |
| 31 | gcvibration = std::make_shared<GCVibrationFactory>(gcadapter); | ||
| 32 | Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration); | ||
| 31 | 33 | ||
| 32 | keyboard = std::make_shared<Keyboard>(); | 34 | keyboard = std::make_shared<Keyboard>(); |
| 33 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | 35 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); |
| @@ -64,9 +66,11 @@ struct InputSubsystem::Impl { | |||
| 64 | #endif | 66 | #endif |
| 65 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | 67 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); |
| 66 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | 68 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); |
| 69 | Input::UnregisterFactory<Input::VibrationDevice>("gcpad"); | ||
| 67 | 70 | ||
| 68 | gcbuttons.reset(); | 71 | gcbuttons.reset(); |
| 69 | gcanalog.reset(); | 72 | gcanalog.reset(); |
| 73 | gcvibration.reset(); | ||
| 70 | 74 | ||
| 71 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); | 75 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); |
| 72 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); | 76 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); |
| @@ -78,7 +82,7 @@ struct InputSubsystem::Impl { | |||
| 78 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { | 82 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { |
| 79 | std::vector<Common::ParamPackage> devices = { | 83 | std::vector<Common::ParamPackage> devices = { |
| 80 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, | 84 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, |
| 81 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, | 85 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}}, |
| 82 | }; | 86 | }; |
| 83 | #ifdef HAVE_SDL2 | 87 | #ifdef HAVE_SDL2 |
| 84 | auto sdl_devices = sdl->GetInputDevices(); | 88 | auto sdl_devices = sdl->GetInputDevices(); |
| @@ -96,10 +100,6 @@ struct InputSubsystem::Impl { | |||
| 96 | if (!params.Has("class") || params.Get("class", "") == "any") { | 100 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 97 | return {}; | 101 | return {}; |
| 98 | } | 102 | } |
| 99 | if (params.Get("class", "") == "key") { | ||
| 100 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 101 | return {}; | ||
| 102 | } | ||
| 103 | if (params.Get("class", "") == "gcpad") { | 103 | if (params.Get("class", "") == "gcpad") { |
| 104 | return gcadapter->GetAnalogMappingForDevice(params); | 104 | return gcadapter->GetAnalogMappingForDevice(params); |
| 105 | } | 105 | } |
| @@ -116,10 +116,6 @@ struct InputSubsystem::Impl { | |||
| 116 | if (!params.Has("class") || params.Get("class", "") == "any") { | 116 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 117 | return {}; | 117 | return {}; |
| 118 | } | 118 | } |
| 119 | if (params.Get("class", "") == "key") { | ||
| 120 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 121 | return {}; | ||
| 122 | } | ||
| 123 | if (params.Get("class", "") == "gcpad") { | 119 | if (params.Get("class", "") == "gcpad") { |
| 124 | return gcadapter->GetButtonMappingForDevice(params); | 120 | return gcadapter->GetButtonMappingForDevice(params); |
| 125 | } | 121 | } |
| @@ -150,6 +146,7 @@ struct InputSubsystem::Impl { | |||
| 150 | #endif | 146 | #endif |
| 151 | std::shared_ptr<GCButtonFactory> gcbuttons; | 147 | std::shared_ptr<GCButtonFactory> gcbuttons; |
| 152 | std::shared_ptr<GCAnalogFactory> gcanalog; | 148 | std::shared_ptr<GCAnalogFactory> gcanalog; |
| 149 | std::shared_ptr<GCVibrationFactory> gcvibration; | ||
| 153 | std::shared_ptr<UDPMotionFactory> udpmotion; | 150 | std::shared_ptr<UDPMotionFactory> udpmotion; |
| 154 | std::shared_ptr<UDPTouchFactory> udptouch; | 151 | std::shared_ptr<UDPTouchFactory> udptouch; |
| 155 | std::shared_ptr<CemuhookUDP::Client> udp; | 152 | std::shared_ptr<CemuhookUDP::Client> udp; |
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h index abb957f04..efe74cf19 100644 --- a/src/input_common/motion_input.h +++ b/src/input_common/motion_input.h | |||
| @@ -13,7 +13,7 @@ namespace InputCommon { | |||
| 13 | 13 | ||
| 14 | class MotionInput { | 14 | class MotionInput { |
| 15 | public: | 15 | public: |
| 16 | MotionInput(f32 new_kp, f32 new_ki, f32 new_kd); | 16 | explicit MotionInput(f32 new_kp, f32 new_ki, f32 new_kd); |
| 17 | 17 | ||
| 18 | MotionInput(const MotionInput&) = default; | 18 | MotionInput(const MotionInput&) = default; |
| 19 | MotionInput& operator=(const MotionInput&) = default; | 19 | MotionInput& operator=(const MotionInput&) = default; |
| @@ -33,16 +33,17 @@ public: | |||
| 33 | void UpdateRotation(u64 elapsed_time); | 33 | void UpdateRotation(u64 elapsed_time); |
| 34 | void UpdateOrientation(u64 elapsed_time); | 34 | void UpdateOrientation(u64 elapsed_time); |
| 35 | 35 | ||
| 36 | std::array<Common::Vec3f, 3> GetOrientation() const; | 36 | [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; |
| 37 | Common::Vec3f GetAcceleration() const; | 37 | [[nodiscard]] Common::Vec3f GetAcceleration() const; |
| 38 | Common::Vec3f GetGyroscope() const; | 38 | [[nodiscard]] Common::Vec3f GetGyroscope() const; |
| 39 | Common::Vec3f GetRotations() const; | 39 | [[nodiscard]] Common::Vec3f GetRotations() const; |
| 40 | Common::Quaternion<f32> GetQuaternion() const; | 40 | [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; |
| 41 | Input::MotionStatus GetMotion() const; | 41 | [[nodiscard]] Input::MotionStatus GetMotion() const; |
| 42 | Input::MotionStatus GetRandomMotion(int accel_magnitude, int gyro_magnitude) const; | 42 | [[nodiscard]] Input::MotionStatus GetRandomMotion(int accel_magnitude, |
| 43 | 43 | int gyro_magnitude) const; | |
| 44 | bool IsMoving(f32 sensitivity) const; | 44 | |
| 45 | bool IsCalibrated(f32 sensitivity) const; | 45 | [[nodiscard]] bool IsMoving(f32 sensitivity) const; |
| 46 | [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; | ||
| 46 | 47 | ||
| 47 | private: | 48 | private: |
| 48 | void ResetOrientation(); | 49 | void ResetOrientation(); |
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index f3554be9a..42bbf14d4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -23,7 +23,7 @@ public: | |||
| 23 | /// Unregisters SDL device factories and shut them down. | 23 | /// Unregisters SDL device factories and shut them down. |
| 24 | virtual ~State() = default; | 24 | virtual ~State() = default; |
| 25 | 25 | ||
| 26 | virtual Pollers GetPollers(Polling::DeviceType type) { | 26 | virtual Pollers GetPollers(Polling::DeviceType) { |
| 27 | return {}; | 27 | return {}; |
| 28 | } | 28 | } |
| 29 | 29 | ||
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 10883e2d9..7827e324c 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -80,30 +80,13 @@ public: | |||
| 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); | 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { | 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { |
| 84 | const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); | 84 | if (sdl_controller) { |
| 85 | const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); | 85 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; |
| 86 | // Lower drastically the number of state changes | 86 | } else if (sdl_joystick) { |
| 87 | if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && | 87 | return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; |
| 88 | raw_amp_high >> 11 == last_state_rumble_high >> 11) { | ||
| 89 | if (raw_amp_low + raw_amp_high != 0 || | ||
| 90 | last_state_rumble_low + last_state_rumble_high == 0) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | // Don't change state if last vibration was < 20ms | ||
| 95 | const auto now = std::chrono::system_clock::now(); | ||
| 96 | if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < | ||
| 97 | std::chrono::milliseconds(20)) { | ||
| 98 | return raw_amp_low + raw_amp_high == 0; | ||
| 99 | } | 88 | } |
| 100 | 89 | ||
| 101 | last_vibration = now; | ||
| 102 | last_state_rumble_low = raw_amp_low; | ||
| 103 | last_state_rumble_high = raw_amp_high; | ||
| 104 | if (sdl_joystick) { | ||
| 105 | SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); | ||
| 106 | } | ||
| 107 | return false; | 90 | return false; |
| 108 | } | 91 | } |
| 109 | 92 | ||
| @@ -172,9 +155,6 @@ private: | |||
| 172 | } state; | 155 | } state; |
| 173 | std::string guid; | 156 | std::string guid; |
| 174 | int port; | 157 | int port; |
| 175 | u16 last_state_rumble_high = 0; | ||
| 176 | u16 last_state_rumble_low = 0; | ||
| 177 | std::chrono::time_point<std::chrono::system_clock> last_vibration; | ||
| 178 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 158 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 179 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 159 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 180 | mutable std::mutex mutex; | 160 | mutable std::mutex mutex; |
| @@ -327,12 +307,6 @@ public: | |||
| 327 | return joystick->GetButton(button); | 307 | return joystick->GetButton(button); |
| 328 | } | 308 | } |
| 329 | 309 | ||
| 330 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 331 | const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); | ||
| 332 | const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); | ||
| 333 | return joystick->RumblePlay(new_amp_low, new_amp_high, 250); | ||
| 334 | } | ||
| 335 | |||
| 336 | private: | 310 | private: |
| 337 | std::shared_ptr<SDLJoystick> joystick; | 311 | std::shared_ptr<SDLJoystick> joystick; |
| 338 | int button; | 312 | int button; |
| @@ -416,6 +390,32 @@ private: | |||
| 416 | const float range; | 390 | const float range; |
| 417 | }; | 391 | }; |
| 418 | 392 | ||
| 393 | class SDLVibration final : public Input::VibrationDevice { | ||
| 394 | public: | ||
| 395 | explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_) | ||
| 396 | : joystick(std::move(joystick_)) {} | ||
| 397 | |||
| 398 | u8 GetStatus() const override { | ||
| 399 | joystick->RumblePlay(1, 1); | ||
| 400 | return joystick->RumblePlay(0, 0); | ||
| 401 | } | ||
| 402 | |||
| 403 | bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high, | ||
| 404 | [[maybe_unused]] f32 freq_high) const override { | ||
| 405 | const auto process_amplitude = [](f32 amplitude) { | ||
| 406 | return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF); | ||
| 407 | }; | ||
| 408 | |||
| 409 | const auto processed_amp_low = process_amplitude(amp_low); | ||
| 410 | const auto processed_amp_high = process_amplitude(amp_high); | ||
| 411 | |||
| 412 | return joystick->RumblePlay(processed_amp_low, processed_amp_high); | ||
| 413 | } | ||
| 414 | |||
| 415 | private: | ||
| 416 | std::shared_ptr<SDLJoystick> joystick; | ||
| 417 | }; | ||
| 418 | |||
| 419 | class SDLDirectionMotion final : public Input::MotionDevice { | 419 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 420 | public: | 420 | public: |
| 421 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 421 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -558,7 +558,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> { | |||
| 558 | public: | 558 | public: |
| 559 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} | 559 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} |
| 560 | /** | 560 | /** |
| 561 | * Creates analog device from joystick axes | 561 | * Creates an analog device from joystick axes |
| 562 | * @param params contains parameters for creating the device: | 562 | * @param params contains parameters for creating the device: |
| 563 | * - "guid": the guid of the joystick to bind | 563 | * - "guid": the guid of the joystick to bind |
| 564 | * - "port": the nth joystick of the same type | 564 | * - "port": the nth joystick of the same type |
| @@ -584,6 +584,26 @@ private: | |||
| 584 | SDLState& state; | 584 | SDLState& state; |
| 585 | }; | 585 | }; |
| 586 | 586 | ||
| 587 | /// An vibration device factory that creates vibration devices from SDL joystick | ||
| 588 | class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 589 | public: | ||
| 590 | explicit SDLVibrationFactory(SDLState& state_) : state(state_) {} | ||
| 591 | /** | ||
| 592 | * Creates a vibration device from a joystick | ||
| 593 | * @param params contains parameters for creating the device: | ||
| 594 | * - "guid": the guid of the joystick to bind | ||
| 595 | * - "port": the nth joystick of the same type | ||
| 596 | */ | ||
| 597 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override { | ||
| 598 | const std::string guid = params.Get("guid", "0"); | ||
| 599 | const int port = params.Get("port", 0); | ||
| 600 | return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port)); | ||
| 601 | } | ||
| 602 | |||
| 603 | private: | ||
| 604 | SDLState& state; | ||
| 605 | }; | ||
| 606 | |||
| 587 | /// A motion device factory that creates motion devices from SDL joystick | 607 | /// A motion device factory that creates motion devices from SDL joystick |
| 588 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { | 608 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { |
| 589 | public: | 609 | public: |
| @@ -650,11 +670,13 @@ private: | |||
| 650 | 670 | ||
| 651 | SDLState::SDLState() { | 671 | SDLState::SDLState() { |
| 652 | using namespace Input; | 672 | using namespace Input; |
| 653 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 654 | button_factory = std::make_shared<SDLButtonFactory>(*this); | 673 | button_factory = std::make_shared<SDLButtonFactory>(*this); |
| 674 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 675 | vibration_factory = std::make_shared<SDLVibrationFactory>(*this); | ||
| 655 | motion_factory = std::make_shared<SDLMotionFactory>(*this); | 676 | motion_factory = std::make_shared<SDLMotionFactory>(*this); |
| 656 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 657 | RegisterFactory<ButtonDevice>("sdl", button_factory); | 677 | RegisterFactory<ButtonDevice>("sdl", button_factory); |
| 678 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 679 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | ||
| 658 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 680 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 659 | 681 | ||
| 660 | // If the frontend is going to manage the event loop, then we don't start one here | 682 | // If the frontend is going to manage the event loop, then we don't start one here |
| @@ -676,7 +698,7 @@ SDLState::SDLState() { | |||
| 676 | using namespace std::chrono_literals; | 698 | using namespace std::chrono_literals; |
| 677 | while (initialized) { | 699 | while (initialized) { |
| 678 | SDL_PumpEvents(); | 700 | SDL_PumpEvents(); |
| 679 | std::this_thread::sleep_for(5ms); | 701 | std::this_thread::sleep_for(1ms); |
| 680 | } | 702 | } |
| 681 | }); | 703 | }); |
| 682 | } | 704 | } |
| @@ -691,6 +713,7 @@ SDLState::~SDLState() { | |||
| 691 | using namespace Input; | 713 | using namespace Input; |
| 692 | UnregisterFactory<ButtonDevice>("sdl"); | 714 | UnregisterFactory<ButtonDevice>("sdl"); |
| 693 | UnregisterFactory<AnalogDevice>("sdl"); | 715 | UnregisterFactory<AnalogDevice>("sdl"); |
| 716 | UnregisterFactory<VibrationDevice>("sdl"); | ||
| 694 | UnregisterFactory<MotionDevice>("sdl"); | 717 | UnregisterFactory<MotionDevice>("sdl"); |
| 695 | 718 | ||
| 696 | CloseJoysticks(); | 719 | CloseJoysticks(); |
| @@ -842,6 +865,8 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve | |||
| 842 | Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, | 865 | Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, |
| 843 | const SDL_GameControllerButtonBind& binding) { | 866 | const SDL_GameControllerButtonBind& binding) { |
| 844 | switch (binding.bindType) { | 867 | switch (binding.bindType) { |
| 868 | case SDL_CONTROLLER_BINDTYPE_NONE: | ||
| 869 | break; | ||
| 845 | case SDL_CONTROLLER_BINDTYPE_AXIS: | 870 | case SDL_CONTROLLER_BINDTYPE_AXIS: |
| 846 | return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); | 871 | return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); |
| 847 | case SDL_CONTROLLER_BINDTYPE_BUTTON: | 872 | case SDL_CONTROLLER_BINDTYPE_BUTTON: |
| @@ -962,7 +987,7 @@ class SDLPoller : public InputCommon::Polling::DevicePoller { | |||
| 962 | public: | 987 | public: |
| 963 | explicit SDLPoller(SDLState& state_) : state(state_) {} | 988 | explicit SDLPoller(SDLState& state_) : state(state_) {} |
| 964 | 989 | ||
| 965 | void Start(const std::string& device_id) override { | 990 | void Start([[maybe_unused]] const std::string& device_id) override { |
| 966 | state.event_queue.Clear(); | 991 | state.event_queue.Clear(); |
| 967 | state.polling = true; | 992 | state.polling = true; |
| 968 | } | 993 | } |
| @@ -1045,7 +1070,6 @@ public: | |||
| 1045 | 1070 | ||
| 1046 | void Start(const std::string& device_id) override { | 1071 | void Start(const std::string& device_id) override { |
| 1047 | SDLPoller::Start(device_id); | 1072 | SDLPoller::Start(device_id); |
| 1048 | // Load the game controller | ||
| 1049 | // Reset stored axes | 1073 | // Reset stored axes |
| 1050 | analog_x_axis = -1; | 1074 | analog_x_axis = -1; |
| 1051 | analog_y_axis = -1; | 1075 | analog_y_axis = -1; |
| @@ -1058,40 +1082,21 @@ public: | |||
| 1058 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { | 1082 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { |
| 1059 | continue; | 1083 | continue; |
| 1060 | } | 1084 | } |
| 1061 | // Simplify controller config by testing if game controller support is enabled. | ||
| 1062 | if (event.type == SDL_JOYAXISMOTION) { | 1085 | if (event.type == SDL_JOYAXISMOTION) { |
| 1063 | const auto axis = event.jaxis.axis; | 1086 | const auto axis = event.jaxis.axis; |
| 1064 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 1087 | // In order to return a complete analog param, we need inputs for both axes. |
| 1065 | auto* const controller = joystick->GetSDLGameController()) { | 1088 | // First we take the x-axis (horizontal) input, then the y-axis (vertical) input. |
| 1066 | const auto axis_left_x = | 1089 | if (analog_x_axis == -1) { |
| 1067 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) | 1090 | analog_x_axis = axis; |
| 1068 | .value.axis; | 1091 | } else if (analog_y_axis == -1 && analog_x_axis != axis) { |
| 1069 | const auto axis_left_y = | 1092 | analog_y_axis = axis; |
| 1070 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) | 1093 | } |
| 1071 | .value.axis; | 1094 | } else { |
| 1072 | const auto axis_right_x = | 1095 | // If the press wasn't accepted as a joy axis, check for a button press |
| 1073 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) | 1096 | auto button_press = button_poller.FromEvent(event); |
| 1074 | .value.axis; | 1097 | if (button_press) { |
| 1075 | const auto axis_right_y = | 1098 | return *button_press; |
| 1076 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) | ||
| 1077 | .value.axis; | ||
| 1078 | |||
| 1079 | if (axis == axis_left_x || axis == axis_left_y) { | ||
| 1080 | analog_x_axis = axis_left_x; | ||
| 1081 | analog_y_axis = axis_left_y; | ||
| 1082 | break; | ||
| 1083 | } else if (axis == axis_right_x || axis == axis_right_y) { | ||
| 1084 | analog_x_axis = axis_right_x; | ||
| 1085 | analog_y_axis = axis_right_y; | ||
| 1086 | break; | ||
| 1087 | } | ||
| 1088 | } | 1099 | } |
| 1089 | } | ||
| 1090 | |||
| 1091 | // If the press wasn't accepted as a joy axis, check for a button press | ||
| 1092 | auto button_press = button_poller.FromEvent(event); | ||
| 1093 | if (button_press) { | ||
| 1094 | return *button_press; | ||
| 1095 | } | 1100 | } |
| 1096 | } | 1101 | } |
| 1097 | 1102 | ||
| @@ -1104,6 +1109,7 @@ public: | |||
| 1104 | return params; | 1109 | return params; |
| 1105 | } | 1110 | } |
| 1106 | } | 1111 | } |
| 1112 | |||
| 1107 | return {}; | 1113 | return {}; |
| 1108 | } | 1114 | } |
| 1109 | 1115 | ||
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index b9bb4dc56..08044b00d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -22,6 +22,7 @@ namespace InputCommon::SDL { | |||
| 22 | class SDLAnalogFactory; | 22 | class SDLAnalogFactory; |
| 23 | class SDLButtonFactory; | 23 | class SDLButtonFactory; |
| 24 | class SDLMotionFactory; | 24 | class SDLMotionFactory; |
| 25 | class SDLVibrationFactory; | ||
| 25 | class SDLJoystick; | 26 | class SDLJoystick; |
| 26 | 27 | ||
| 27 | class SDLState : public State { | 28 | class SDLState : public State { |
| @@ -72,6 +73,7 @@ private: | |||
| 72 | 73 | ||
| 73 | std::shared_ptr<SDLButtonFactory> button_factory; | 74 | std::shared_ptr<SDLButtonFactory> button_factory; |
| 74 | std::shared_ptr<SDLAnalogFactory> analog_factory; | 75 | std::shared_ptr<SDLAnalogFactory> analog_factory; |
| 76 | std::shared_ptr<SDLVibrationFactory> vibration_factory; | ||
| 75 | std::shared_ptr<SDLMotionFactory> motion_factory; | 77 | std::shared_ptr<SDLMotionFactory> motion_factory; |
| 76 | 78 | ||
| 77 | bool start_thread = false; | 79 | bool start_thread = false; |
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp index b66c05856..557e7a9a0 100644 --- a/src/input_common/settings.cpp +++ b/src/input_common/settings.cpp | |||
| @@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{ | |||
| 14 | }}; | 14 | }}; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace NativeMotion { | ||
| 18 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 19 | "motionleft", | ||
| 20 | "motionright", | ||
| 21 | }}; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace NativeAnalog { | 17 | namespace NativeAnalog { |
| 25 | const std::array<const char*, NumAnalogs> mapping = {{ | 18 | const std::array<const char*, NumAnalogs> mapping = {{ |
| 26 | "lstick", | 19 | "lstick", |
| @@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{ | |||
| 28 | }}; | 21 | }}; |
| 29 | } | 22 | } |
| 30 | 23 | ||
| 24 | namespace NativeVibration { | ||
| 25 | const std::array<const char*, NumVibrations> mapping = {{ | ||
| 26 | "left_vibration_device", | ||
| 27 | "right_vibration_device", | ||
| 28 | }}; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace NativeMotion { | ||
| 32 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 33 | "motionleft", | ||
| 34 | "motionright", | ||
| 35 | }}; | ||
| 36 | } | ||
| 37 | |||
| 31 | namespace NativeMouseButton { | 38 | namespace NativeMouseButton { |
| 32 | const std::array<const char*, NumMouseButtons> mapping = {{ | 39 | const std::array<const char*, NumMouseButtons> mapping = {{ |
| 33 | "left", | 40 | "left", |
diff --git a/src/input_common/settings.h b/src/input_common/settings.h index f52d28540..75486554b 100644 --- a/src/input_common/settings.h +++ b/src/input_common/settings.h | |||
| @@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs; | |||
| 66 | extern const std::array<const char*, NumAnalogs> mapping; | 66 | extern const std::array<const char*, NumAnalogs> mapping; |
| 67 | } // namespace NativeAnalog | 67 | } // namespace NativeAnalog |
| 68 | 68 | ||
| 69 | namespace NativeVibration { | ||
| 70 | enum Values : int { | ||
| 71 | LeftVibrationDevice, | ||
| 72 | RightVibrationDevice, | ||
| 73 | |||
| 74 | NumVibrations, | ||
| 75 | }; | ||
| 76 | |||
| 77 | constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice; | ||
| 78 | constexpr int VIBRATION_HID_END = NumVibrations; | ||
| 79 | constexpr int NUM_VIBRATIONS_HID = NumVibrations; | ||
| 80 | |||
| 81 | extern const std::array<const char*, NumVibrations> mapping; | ||
| 82 | }; // namespace NativeVibration | ||
| 83 | |||
| 69 | namespace NativeMotion { | 84 | namespace NativeMotion { |
| 70 | enum Values : int { | 85 | enum Values : int { |
| 71 | MOTIONLEFT, | 86 | MotionLeft, |
| 72 | MOTIONRIGHT, | 87 | MotionRight, |
| 73 | 88 | ||
| 74 | NumMotions, | 89 | NumMotions, |
| 75 | }; | 90 | }; |
| 76 | 91 | ||
| 77 | constexpr int MOTION_HID_BEGIN = MOTIONLEFT; | 92 | constexpr int MOTION_HID_BEGIN = MotionLeft; |
| 78 | constexpr int MOTION_HID_END = NumMotions; | 93 | constexpr int MOTION_HID_END = NumMotions; |
| 79 | constexpr int NUM_MOTION_HID = NumMotions; | 94 | constexpr int NUM_MOTIONS_HID = NumMotions; |
| 80 | 95 | ||
| 81 | extern const std::array<const char*, NumMotions> mapping; | 96 | extern const std::array<const char*, NumMotions> mapping; |
| 82 | } // namespace NativeMotion | 97 | } // namespace NativeMotion |
| @@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | |||
| 305 | 320 | ||
| 306 | } // namespace NativeKeyboard | 321 | } // namespace NativeKeyboard |
| 307 | 322 | ||
| 308 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 309 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | 323 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; |
| 310 | using MotionRaw = std::array<std::string, NativeMotion::NumMotions>; | 324 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; |
| 325 | using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>; | ||
| 326 | using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>; | ||
| 327 | |||
| 311 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | 328 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; |
| 312 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | 329 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; |
| 313 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | 330 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; |
| @@ -330,7 +347,11 @@ struct PlayerInput { | |||
| 330 | ControllerType controller_type; | 347 | ControllerType controller_type; |
| 331 | ButtonsRaw buttons; | 348 | ButtonsRaw buttons; |
| 332 | AnalogsRaw analogs; | 349 | AnalogsRaw analogs; |
| 333 | MotionRaw motions; | 350 | VibrationsRaw vibrations; |
| 351 | MotionsRaw motions; | ||
| 352 | |||
| 353 | bool vibration_enabled; | ||
| 354 | int vibration_strength; | ||
| 334 | 355 | ||
| 335 | u32 body_color_left; | 356 | u32 body_color_left; |
| 336 | u32 body_color_right; | 357 | u32 body_color_right; |
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index c37716aae..a07124a86 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -44,8 +44,7 @@ private: | |||
| 44 | std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map; | 44 | std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map; |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create( | 47 | std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) { |
| 48 | const Common::ParamPackage& params) { | ||
| 49 | return std::make_unique<TouchFromButtonDevice>(); | 48 | return std::make_unique<TouchFromButtonDevice>(); |
| 50 | } | 49 | } |
| 51 | 50 | ||
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 7039d6fc3..c0bb90048 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -63,7 +63,7 @@ public: | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | private: | 65 | private: |
| 66 | void HandleReceive(const boost::system::error_code& error, std::size_t bytes_transferred) { | 66 | void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) { |
| 67 | if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { | 67 | if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { |
| 68 | switch (*type) { | 68 | switch (*type) { |
| 69 | case Type::Version: { | 69 | case Type::Version: { |
| @@ -90,7 +90,7 @@ private: | |||
| 90 | StartReceive(); | 90 | StartReceive(); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | void HandleSend(const boost::system::error_code& error) { | 93 | void HandleSend(const boost::system::error_code&) { |
| 94 | boost::system::error_code _ignored{}; | 94 | boost::system::error_code _ignored{}; |
| 95 | // Send a request for getting port info for the pad | 95 | // Send a request for getting port info for the pad |
| 96 | const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; | 96 | const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; |
| @@ -189,11 +189,11 @@ void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_ind | |||
| 189 | StartCommunication(client, host, port, pad_index, client_id); | 189 | StartCommunication(client, host, port, pad_index, client_id); |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | void Client::OnVersion(Response::Version data) { | 192 | void Client::OnVersion([[maybe_unused]] Response::Version data) { |
| 193 | LOG_TRACE(Input, "Version packet received: {}", data.version); | 193 | LOG_TRACE(Input, "Version packet received: {}", data.version); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | void Client::OnPortInfo(Response::PortInfo data) { | 196 | void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { |
| 197 | LOG_TRACE(Input, "PortInfo packet received: {}", data.model); | 197 | LOG_TRACE(Input, "PortInfo packet received: {}", data.model); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| @@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 344 | }; | 344 | }; |
| 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; | 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; |
| 346 | std::thread worker_thread{SocketLoop, &socket}; | 346 | std::thread worker_thread{SocketLoop, &socket}; |
| 347 | const bool result = success_event.WaitFor(std::chrono::seconds(8)); | 347 | const bool result = success_event.WaitFor(std::chrono::seconds(5)); |
| 348 | socket.Stop(); | 348 | socket.Stop(); |
| 349 | worker_thread.join(); | 349 | worker_thread.join(); |
| 350 | if (result) { | 350 | if (result) { |
| @@ -369,7 +369,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 369 | u16 max_y{}; | 369 | u16 max_y{}; |
| 370 | 370 | ||
| 371 | Status current_status{Status::Initialized}; | 371 | Status current_status{Status::Initialized}; |
| 372 | SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {}, | 372 | SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, |
| 373 | [&](Response::PadData data) { | 373 | [&](Response::PadData data) { |
| 374 | if (current_status == Status::Initialized) { | 374 | if (current_status == Status::Initialized) { |
| 375 | // Receiving data means the communication is ready now | 375 | // Receiving data means the communication is ready now |
diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h index 3ba4d1fc8..fc1aea4b9 100644 --- a/src/input_common/udp/protocol.h +++ b/src/input_common/udp/protocol.h | |||
| @@ -7,7 +7,16 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <type_traits> | 9 | #include <type_traits> |
| 10 | |||
| 11 | #ifdef _MSC_VER | ||
| 12 | #pragma warning(push) | ||
| 13 | #pragma warning(disable : 4701) | ||
| 14 | #endif | ||
| 10 | #include <boost/crc.hpp> | 15 | #include <boost/crc.hpp> |
| 16 | #ifdef _MSC_VER | ||
| 17 | #pragma warning(pop) | ||
| 18 | #endif | ||
| 19 | |||
| 11 | #include "common/bit_field.h" | 20 | #include "common/bit_field.h" |
| 12 | #include "common/swap.h" | 21 | #include "common/swap.h" |
| 13 | 22 | ||
| @@ -93,7 +102,7 @@ static_assert(std::is_trivially_copyable_v<PadData>, | |||
| 93 | 102 | ||
| 94 | /** | 103 | /** |
| 95 | * Creates a message with the proper header data that can be sent to the server. | 104 | * Creates a message with the proper header data that can be sent to the server. |
| 96 | * @param T data Request body to send | 105 | * @param data Request body to send |
| 97 | * @param client_id ID of the udp client (usually not checked on the server) | 106 | * @param client_id ID of the udp client (usually not checked on the server) |
| 98 | */ | 107 | */ |
| 99 | template <typename T> | 108 | template <typename T> |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 57ebc785f..6287df633 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -124,6 +124,112 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 124 | mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true; | 124 | mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { | ||
| 128 | if (executing_macro == 0) { | ||
| 129 | // A macro call must begin by writing the macro method's register, not its argument. | ||
| 130 | ASSERT_MSG((method % 2) == 0, | ||
| 131 | "Can't start macro execution by writing to the ARGS register"); | ||
| 132 | executing_macro = method; | ||
| 133 | } | ||
| 134 | |||
| 135 | macro_params.insert(macro_params.end(), base_start, base_start + amount); | ||
| 136 | |||
| 137 | // Call the macro when there are no more parameters in the command buffer | ||
| 138 | if (is_last_call) { | ||
| 139 | CallMacroMethod(executing_macro, macro_params); | ||
| 140 | macro_params.clear(); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { | ||
| 145 | // Keep track of the register value in shadow_state when requested. | ||
| 146 | const auto control = shadow_state.shadow_ram_control; | ||
| 147 | if (control == Regs::ShadowRamControl::Track || | ||
| 148 | control == Regs::ShadowRamControl::TrackWithFilter) { | ||
| 149 | shadow_state.reg_array[method] = argument; | ||
| 150 | return argument; | ||
| 151 | } | ||
| 152 | if (control == Regs::ShadowRamControl::Replay) { | ||
| 153 | return shadow_state.reg_array[method]; | ||
| 154 | } | ||
| 155 | return argument; | ||
| 156 | } | ||
| 157 | |||
| 158 | void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) { | ||
| 159 | if (regs.reg_array[method] == argument) { | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | regs.reg_array[method] = argument; | ||
| 163 | |||
| 164 | for (const auto& table : dirty.tables) { | ||
| 165 | dirty.flags[table[method]] = true; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, | ||
| 170 | bool is_last_call) { | ||
| 171 | switch (method) { | ||
| 172 | case MAXWELL3D_REG_INDEX(wait_for_idle): | ||
| 173 | return rasterizer->WaitForIdle(); | ||
| 174 | case MAXWELL3D_REG_INDEX(shadow_ram_control): | ||
| 175 | shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument); | ||
| 176 | return; | ||
| 177 | case MAXWELL3D_REG_INDEX(macros.data): | ||
| 178 | return macro_engine->AddCode(regs.macros.upload_address, argument); | ||
| 179 | case MAXWELL3D_REG_INDEX(macros.bind): | ||
| 180 | return ProcessMacroBind(argument); | ||
| 181 | case MAXWELL3D_REG_INDEX(firmware[4]): | ||
| 182 | return ProcessFirmwareCall4(); | ||
| 183 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): | ||
| 184 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]): | ||
| 185 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]): | ||
| 186 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]): | ||
| 187 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]): | ||
| 188 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]): | ||
| 189 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]): | ||
| 190 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]): | ||
| 191 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]): | ||
| 192 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]): | ||
| 193 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]): | ||
| 194 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]): | ||
| 195 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): | ||
| 196 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): | ||
| 197 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): | ||
| 198 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): | ||
| 199 | return StartCBData(method); | ||
| 200 | case MAXWELL3D_REG_INDEX(cb_bind[0]): | ||
| 201 | return ProcessCBBind(0); | ||
| 202 | case MAXWELL3D_REG_INDEX(cb_bind[1]): | ||
| 203 | return ProcessCBBind(1); | ||
| 204 | case MAXWELL3D_REG_INDEX(cb_bind[2]): | ||
| 205 | return ProcessCBBind(2); | ||
| 206 | case MAXWELL3D_REG_INDEX(cb_bind[3]): | ||
| 207 | return ProcessCBBind(3); | ||
| 208 | case MAXWELL3D_REG_INDEX(cb_bind[4]): | ||
| 209 | return ProcessCBBind(4); | ||
| 210 | case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): | ||
| 211 | return DrawArrays(); | ||
| 212 | case MAXWELL3D_REG_INDEX(clear_buffers): | ||
| 213 | return ProcessClearBuffers(); | ||
| 214 | case MAXWELL3D_REG_INDEX(query.query_get): | ||
| 215 | return ProcessQueryGet(); | ||
| 216 | case MAXWELL3D_REG_INDEX(condition.mode): | ||
| 217 | return ProcessQueryCondition(); | ||
| 218 | case MAXWELL3D_REG_INDEX(counter_reset): | ||
| 219 | return ProcessCounterReset(); | ||
| 220 | case MAXWELL3D_REG_INDEX(sync_info): | ||
| 221 | return ProcessSyncPoint(); | ||
| 222 | case MAXWELL3D_REG_INDEX(exec_upload): | ||
| 223 | return upload_state.ProcessExec(regs.exec_upload.linear != 0); | ||
| 224 | case MAXWELL3D_REG_INDEX(data_upload): | ||
| 225 | upload_state.ProcessData(argument, is_last_call); | ||
| 226 | if (is_last_call) { | ||
| 227 | OnMemoryWrite(); | ||
| 228 | } | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 127 | void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) { | 233 | void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) { |
| 128 | // Reset the current macro. | 234 | // Reset the current macro. |
| 129 | executing_macro = 0; | 235 | executing_macro = 0; |
| @@ -157,142 +263,16 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 157 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was | 263 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was |
| 158 | // uploaded to the GPU during initialization. | 264 | // uploaded to the GPU during initialization. |
| 159 | if (method >= MacroRegistersStart) { | 265 | if (method >= MacroRegistersStart) { |
| 160 | // We're trying to execute a macro | 266 | ProcessMacro(method, &method_argument, 1, is_last_call); |
| 161 | if (executing_macro == 0) { | ||
| 162 | // A macro call must begin by writing the macro method's register, not its argument. | ||
| 163 | ASSERT_MSG((method % 2) == 0, | ||
| 164 | "Can't start macro execution by writing to the ARGS register"); | ||
| 165 | executing_macro = method; | ||
| 166 | } | ||
| 167 | |||
| 168 | macro_params.push_back(method_argument); | ||
| 169 | |||
| 170 | // Call the macro when there are no more parameters in the command buffer | ||
| 171 | if (is_last_call) { | ||
| 172 | CallMacroMethod(executing_macro, macro_params); | ||
| 173 | macro_params.clear(); | ||
| 174 | } | ||
| 175 | return; | 267 | return; |
| 176 | } | 268 | } |
| 177 | 269 | ||
| 178 | ASSERT_MSG(method < Regs::NUM_REGS, | 270 | ASSERT_MSG(method < Regs::NUM_REGS, |
| 179 | "Invalid Maxwell3D register, increase the size of the Regs structure"); | 271 | "Invalid Maxwell3D register, increase the size of the Regs structure"); |
| 180 | 272 | ||
| 181 | u32 arg = method_argument; | 273 | const u32 argument = ProcessShadowRam(method, method_argument); |
| 182 | // Keep track of the register value in shadow_state when requested. | 274 | ProcessDirtyRegisters(method, argument); |
| 183 | if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track || | 275 | ProcessMethodCall(method, argument, method_argument, is_last_call); |
| 184 | shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) { | ||
| 185 | shadow_state.reg_array[method] = arg; | ||
| 186 | } else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) { | ||
| 187 | arg = shadow_state.reg_array[method]; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (regs.reg_array[method] != arg) { | ||
| 191 | regs.reg_array[method] = arg; | ||
| 192 | |||
| 193 | for (const auto& table : dirty.tables) { | ||
| 194 | dirty.flags[table[method]] = true; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | switch (method) { | ||
| 199 | case MAXWELL3D_REG_INDEX(wait_for_idle): { | ||
| 200 | rasterizer->WaitForIdle(); | ||
| 201 | break; | ||
| 202 | } | ||
| 203 | case MAXWELL3D_REG_INDEX(shadow_ram_control): { | ||
| 204 | shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_argument); | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | case MAXWELL3D_REG_INDEX(macros.data): { | ||
| 208 | macro_engine->AddCode(regs.macros.upload_address, arg); | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | case MAXWELL3D_REG_INDEX(macros.bind): { | ||
| 212 | ProcessMacroBind(arg); | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | case MAXWELL3D_REG_INDEX(firmware[4]): { | ||
| 216 | ProcessFirmwareCall4(); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): | ||
| 220 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]): | ||
| 221 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]): | ||
| 222 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]): | ||
| 223 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]): | ||
| 224 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]): | ||
| 225 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]): | ||
| 226 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]): | ||
| 227 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]): | ||
| 228 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]): | ||
| 229 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]): | ||
| 230 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]): | ||
| 231 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): | ||
| 232 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): | ||
| 233 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): | ||
| 234 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { | ||
| 235 | StartCBData(method); | ||
| 236 | break; | ||
| 237 | } | ||
| 238 | case MAXWELL3D_REG_INDEX(cb_bind[0]): { | ||
| 239 | ProcessCBBind(0); | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | case MAXWELL3D_REG_INDEX(cb_bind[1]): { | ||
| 243 | ProcessCBBind(1); | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | case MAXWELL3D_REG_INDEX(cb_bind[2]): { | ||
| 247 | ProcessCBBind(2); | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | case MAXWELL3D_REG_INDEX(cb_bind[3]): { | ||
| 251 | ProcessCBBind(3); | ||
| 252 | break; | ||
| 253 | } | ||
| 254 | case MAXWELL3D_REG_INDEX(cb_bind[4]): { | ||
| 255 | ProcessCBBind(4); | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): { | ||
| 259 | DrawArrays(); | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | case MAXWELL3D_REG_INDEX(clear_buffers): { | ||
| 263 | ProcessClearBuffers(); | ||
| 264 | break; | ||
| 265 | } | ||
| 266 | case MAXWELL3D_REG_INDEX(query.query_get): { | ||
| 267 | ProcessQueryGet(); | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | case MAXWELL3D_REG_INDEX(condition.mode): { | ||
| 271 | ProcessQueryCondition(); | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | case MAXWELL3D_REG_INDEX(counter_reset): { | ||
| 275 | ProcessCounterReset(); | ||
| 276 | break; | ||
| 277 | } | ||
| 278 | case MAXWELL3D_REG_INDEX(sync_info): { | ||
| 279 | ProcessSyncPoint(); | ||
| 280 | break; | ||
| 281 | } | ||
| 282 | case MAXWELL3D_REG_INDEX(exec_upload): { | ||
| 283 | upload_state.ProcessExec(regs.exec_upload.linear != 0); | ||
| 284 | break; | ||
| 285 | } | ||
| 286 | case MAXWELL3D_REG_INDEX(data_upload): { | ||
| 287 | upload_state.ProcessData(arg, is_last_call); | ||
| 288 | if (is_last_call) { | ||
| 289 | OnMemoryWrite(); | ||
| 290 | } | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | default: | ||
| 294 | break; | ||
| 295 | } | ||
| 296 | } | 276 | } |
| 297 | 277 | ||
| 298 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | 278 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, |
| @@ -300,23 +280,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | |||
| 300 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was | 280 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was |
| 301 | // uploaded to the GPU during initialization. | 281 | // uploaded to the GPU during initialization. |
| 302 | if (method >= MacroRegistersStart) { | 282 | if (method >= MacroRegistersStart) { |
| 303 | // We're trying to execute a macro | 283 | ProcessMacro(method, base_start, amount, amount == methods_pending); |
| 304 | if (executing_macro == 0) { | ||
| 305 | // A macro call must begin by writing the macro method's register, not its argument. | ||
| 306 | ASSERT_MSG((method % 2) == 0, | ||
| 307 | "Can't start macro execution by writing to the ARGS register"); | ||
| 308 | executing_macro = method; | ||
| 309 | } | ||
| 310 | |||
| 311 | for (std::size_t i = 0; i < amount; i++) { | ||
| 312 | macro_params.push_back(base_start[i]); | ||
| 313 | } | ||
| 314 | |||
| 315 | // Call the macro when there are no more parameters in the command buffer | ||
| 316 | if (amount == methods_pending) { | ||
| 317 | CallMacroMethod(executing_macro, macro_params); | ||
| 318 | macro_params.clear(); | ||
| 319 | } | ||
| 320 | return; | 284 | return; |
| 321 | } | 285 | } |
| 322 | switch (method) { | 286 | switch (method) { |
| @@ -335,15 +299,14 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | |||
| 335 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): | 299 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): |
| 336 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): | 300 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): |
| 337 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): | 301 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): |
| 338 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { | 302 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): |
| 339 | ProcessCBMultiData(method, base_start, amount); | 303 | ProcessCBMultiData(method, base_start, amount); |
| 340 | break; | 304 | break; |
| 341 | } | 305 | default: |
| 342 | default: { | ||
| 343 | for (std::size_t i = 0; i < amount; i++) { | 306 | for (std::size_t i = 0; i < amount; i++) { |
| 344 | CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); | 307 | CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); |
| 345 | } | 308 | } |
| 346 | } | 309 | break; |
| 347 | } | 310 | } |
| 348 | } | 311 | } |
| 349 | 312 | ||
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index bc289c55d..1cbe8fe67 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -1461,6 +1461,14 @@ public: | |||
| 1461 | private: | 1461 | private: |
| 1462 | void InitializeRegisterDefaults(); | 1462 | void InitializeRegisterDefaults(); |
| 1463 | 1463 | ||
| 1464 | void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call); | ||
| 1465 | |||
| 1466 | u32 ProcessShadowRam(u32 method, u32 argument); | ||
| 1467 | |||
| 1468 | void ProcessDirtyRegisters(u32 method, u32 argument); | ||
| 1469 | |||
| 1470 | void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call); | ||
| 1471 | |||
| 1464 | Core::System& system; | 1472 | Core::System& system; |
| 1465 | MemoryManager& memory_manager; | 1473 | MemoryManager& memory_manager; |
| 1466 | 1474 | ||
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index a3c05d1b0..37d17efdc 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -32,31 +32,31 @@ struct Register { | |||
| 32 | 32 | ||
| 33 | constexpr Register() = default; | 33 | constexpr Register() = default; |
| 34 | 34 | ||
| 35 | constexpr Register(u64 value) : value(value) {} | 35 | constexpr Register(u64 value_) : value(value_) {} |
| 36 | 36 | ||
| 37 | constexpr operator u64() const { | 37 | [[nodiscard]] constexpr operator u64() const { |
| 38 | return value; | 38 | return value; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | template <typename T> | 41 | template <typename T> |
| 42 | constexpr u64 operator-(const T& oth) const { | 42 | [[nodiscard]] constexpr u64 operator-(const T& oth) const { |
| 43 | return value - oth; | 43 | return value - oth; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | template <typename T> | 46 | template <typename T> |
| 47 | constexpr u64 operator&(const T& oth) const { | 47 | [[nodiscard]] constexpr u64 operator&(const T& oth) const { |
| 48 | return value & oth; | 48 | return value & oth; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | constexpr u64 operator&(const Register& oth) const { | 51 | [[nodiscard]] constexpr u64 operator&(const Register& oth) const { |
| 52 | return value & oth.value; | 52 | return value & oth.value; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | constexpr u64 operator~() const { | 55 | [[nodiscard]] constexpr u64 operator~() const { |
| 56 | return ~value; | 56 | return ~value; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | u64 GetSwizzledIndex(u64 elem) const { | 59 | [[nodiscard]] u64 GetSwizzledIndex(u64 elem) const { |
| 60 | elem = (value + elem) & 3; | 60 | elem = (value + elem) & 3; |
| 61 | return (value & ~3) + elem; | 61 | return (value & ~3) + elem; |
| 62 | } | 62 | } |
| @@ -75,7 +75,7 @@ enum class AttributeSize : u64 { | |||
| 75 | union Attribute { | 75 | union Attribute { |
| 76 | Attribute() = default; | 76 | Attribute() = default; |
| 77 | 77 | ||
| 78 | constexpr explicit Attribute(u64 value) : value(value) {} | 78 | constexpr explicit Attribute(u64 value_) : value(value_) {} |
| 79 | 79 | ||
| 80 | enum class Index : u64 { | 80 | enum class Index : u64 { |
| 81 | LayerViewportPointSize = 6, | 81 | LayerViewportPointSize = 6, |
| @@ -107,7 +107,7 @@ union Attribute { | |||
| 107 | BitField<31, 1, u64> patch; | 107 | BitField<31, 1, u64> patch; |
| 108 | BitField<47, 3, AttributeSize> size; | 108 | BitField<47, 3, AttributeSize> size; |
| 109 | 109 | ||
| 110 | bool IsPhysical() const { | 110 | [[nodiscard]] bool IsPhysical() const { |
| 111 | return patch == 0 && element == 0 && static_cast<u64>(index.Value()) == 0; | 111 | return patch == 0 && element == 0 && static_cast<u64>(index.Value()) == 0; |
| 112 | } | 112 | } |
| 113 | } fmt20; | 113 | } fmt20; |
| @@ -124,7 +124,7 @@ union Attribute { | |||
| 124 | union Sampler { | 124 | union Sampler { |
| 125 | Sampler() = default; | 125 | Sampler() = default; |
| 126 | 126 | ||
| 127 | constexpr explicit Sampler(u64 value) : value(value) {} | 127 | constexpr explicit Sampler(u64 value_) : value(value_) {} |
| 128 | 128 | ||
| 129 | enum class Index : u64 { | 129 | enum class Index : u64 { |
| 130 | Sampler_0 = 8, | 130 | Sampler_0 = 8, |
| @@ -137,7 +137,7 @@ union Sampler { | |||
| 137 | union Image { | 137 | union Image { |
| 138 | Image() = default; | 138 | Image() = default; |
| 139 | 139 | ||
| 140 | constexpr explicit Image(u64 value) : value{value} {} | 140 | constexpr explicit Image(u64 value_) : value{value_} {} |
| 141 | 141 | ||
| 142 | BitField<36, 13, u64> index; | 142 | BitField<36, 13, u64> index; |
| 143 | u64 value; | 143 | u64 value; |
| @@ -505,14 +505,14 @@ struct IpaMode { | |||
| 505 | IpaInterpMode interpolation_mode; | 505 | IpaInterpMode interpolation_mode; |
| 506 | IpaSampleMode sampling_mode; | 506 | IpaSampleMode sampling_mode; |
| 507 | 507 | ||
| 508 | bool operator==(const IpaMode& a) const { | 508 | [[nodiscard]] bool operator==(const IpaMode& a) const { |
| 509 | return std::tie(interpolation_mode, sampling_mode) == | 509 | return std::tie(interpolation_mode, sampling_mode) == |
| 510 | std::tie(a.interpolation_mode, a.sampling_mode); | 510 | std::tie(a.interpolation_mode, a.sampling_mode); |
| 511 | } | 511 | } |
| 512 | bool operator!=(const IpaMode& a) const { | 512 | [[nodiscard]] bool operator!=(const IpaMode& a) const { |
| 513 | return !operator==(a); | 513 | return !operator==(a); |
| 514 | } | 514 | } |
| 515 | bool operator<(const IpaMode& a) const { | 515 | [[nodiscard]] bool operator<(const IpaMode& a) const { |
| 516 | return std::tie(interpolation_mode, sampling_mode) < | 516 | return std::tie(interpolation_mode, sampling_mode) < |
| 517 | std::tie(a.interpolation_mode, a.sampling_mode); | 517 | std::tie(a.interpolation_mode, a.sampling_mode); |
| 518 | } | 518 | } |
| @@ -658,10 +658,10 @@ union Instruction { | |||
| 658 | return *this; | 658 | return *this; |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | constexpr Instruction(u64 value) : value{value} {} | 661 | constexpr Instruction(u64 value_) : value{value_} {} |
| 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} | 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} |
| 663 | 663 | ||
| 664 | constexpr bool Bit(u64 offset) const { | 664 | [[nodiscard]] constexpr bool Bit(u64 offset) const { |
| 665 | return ((value >> offset) & 1) != 0; | 665 | return ((value >> offset) & 1) != 0; |
| 666 | } | 666 | } |
| 667 | 667 | ||
| @@ -746,34 +746,34 @@ union Instruction { | |||
| 746 | BitField<28, 8, u64> imm_lut28; | 746 | BitField<28, 8, u64> imm_lut28; |
| 747 | BitField<48, 8, u64> imm_lut48; | 747 | BitField<48, 8, u64> imm_lut48; |
| 748 | 748 | ||
| 749 | u32 GetImmLut28() const { | 749 | [[nodiscard]] u32 GetImmLut28() const { |
| 750 | return static_cast<u32>(imm_lut28); | 750 | return static_cast<u32>(imm_lut28); |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | u32 GetImmLut48() const { | 753 | [[nodiscard]] u32 GetImmLut48() const { |
| 754 | return static_cast<u32>(imm_lut48); | 754 | return static_cast<u32>(imm_lut48); |
| 755 | } | 755 | } |
| 756 | } lop3; | 756 | } lop3; |
| 757 | 757 | ||
| 758 | u16 GetImm20_16() const { | 758 | [[nodiscard]] u16 GetImm20_16() const { |
| 759 | return static_cast<u16>(imm20_16); | 759 | return static_cast<u16>(imm20_16); |
| 760 | } | 760 | } |
| 761 | 761 | ||
| 762 | u32 GetImm20_19() const { | 762 | [[nodiscard]] u32 GetImm20_19() const { |
| 763 | u32 imm{static_cast<u32>(imm20_19)}; | 763 | u32 imm{static_cast<u32>(imm20_19)}; |
| 764 | imm <<= 12; | 764 | imm <<= 12; |
| 765 | imm |= negate_imm ? 0x80000000 : 0; | 765 | imm |= negate_imm ? 0x80000000 : 0; |
| 766 | return imm; | 766 | return imm; |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | u32 GetImm20_32() const { | 769 | [[nodiscard]] u32 GetImm20_32() const { |
| 770 | return static_cast<u32>(imm20_32); | 770 | return static_cast<u32>(imm20_32); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | s32 GetSignedImm20_20() const { | 773 | [[nodiscard]] s32 GetSignedImm20_20() const { |
| 774 | u32 immediate = static_cast<u32>(imm20_19 | (negate_imm << 19)); | 774 | const auto immediate = static_cast<u32>(imm20_19 | (negate_imm << 19)); |
| 775 | // Sign extend the 20-bit value. | 775 | // Sign extend the 20-bit value. |
| 776 | u32 mask = 1U << (20 - 1); | 776 | const auto mask = 1U << (20 - 1); |
| 777 | return static_cast<s32>((immediate ^ mask) - mask); | 777 | return static_cast<s32>((immediate ^ mask) - mask); |
| 778 | } | 778 | } |
| 779 | } alu; | 779 | } alu; |
| @@ -857,7 +857,7 @@ union Instruction { | |||
| 857 | BitField<56, 1, u64> second_negate; | 857 | BitField<56, 1, u64> second_negate; |
| 858 | BitField<30, 9, u64> second; | 858 | BitField<30, 9, u64> second; |
| 859 | 859 | ||
| 860 | u32 PackImmediates() const { | 860 | [[nodiscard]] u32 PackImmediates() const { |
| 861 | // Immediates are half floats shifted. | 861 | // Immediates are half floats shifted. |
| 862 | constexpr u32 imm_shift = 6; | 862 | constexpr u32 imm_shift = 6; |
| 863 | return static_cast<u32>((first << imm_shift) | (second << (16 + imm_shift))); | 863 | return static_cast<u32>((first << imm_shift) | (second << (16 + imm_shift))); |
| @@ -1033,7 +1033,7 @@ union Instruction { | |||
| 1033 | BitField<28, 2, AtomicType> type; | 1033 | BitField<28, 2, AtomicType> type; |
| 1034 | BitField<30, 22, s64> offset; | 1034 | BitField<30, 22, s64> offset; |
| 1035 | 1035 | ||
| 1036 | s32 GetImmediateOffset() const { | 1036 | [[nodiscard]] s32 GetImmediateOffset() const { |
| 1037 | return static_cast<s32>(offset << 2); | 1037 | return static_cast<s32>(offset << 2); |
| 1038 | } | 1038 | } |
| 1039 | } atoms; | 1039 | } atoms; |
| @@ -1215,7 +1215,7 @@ union Instruction { | |||
| 1215 | BitField<39, 4, u64> rounding; | 1215 | BitField<39, 4, u64> rounding; |
| 1216 | // H0, H1 extract for F16 missing | 1216 | // H0, H1 extract for F16 missing |
| 1217 | BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value | 1217 | BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value |
| 1218 | F2fRoundingOp GetRoundingMode() const { | 1218 | [[nodiscard]] F2fRoundingOp GetRoundingMode() const { |
| 1219 | constexpr u64 rounding_mask = 0x0B; | 1219 | constexpr u64 rounding_mask = 0x0B; |
| 1220 | return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask); | 1220 | return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask); |
| 1221 | } | 1221 | } |
| @@ -1239,15 +1239,15 @@ union Instruction { | |||
| 1239 | BitField<54, 1, u64> aoffi_flag; | 1239 | BitField<54, 1, u64> aoffi_flag; |
| 1240 | BitField<55, 3, TextureProcessMode> process_mode; | 1240 | BitField<55, 3, TextureProcessMode> process_mode; |
| 1241 | 1241 | ||
| 1242 | bool IsComponentEnabled(std::size_t component) const { | 1242 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1243 | return ((1ull << component) & component_mask) != 0; | 1243 | return ((1ULL << component) & component_mask) != 0; |
| 1244 | } | 1244 | } |
| 1245 | 1245 | ||
| 1246 | TextureProcessMode GetTextureProcessMode() const { | 1246 | [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { |
| 1247 | return process_mode; | 1247 | return process_mode; |
| 1248 | } | 1248 | } |
| 1249 | 1249 | ||
| 1250 | bool UsesMiscMode(TextureMiscMode mode) const { | 1250 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1251 | switch (mode) { | 1251 | switch (mode) { |
| 1252 | case TextureMiscMode::DC: | 1252 | case TextureMiscMode::DC: |
| 1253 | return dc_flag != 0; | 1253 | return dc_flag != 0; |
| @@ -1271,15 +1271,15 @@ union Instruction { | |||
| 1271 | BitField<36, 1, u64> aoffi_flag; | 1271 | BitField<36, 1, u64> aoffi_flag; |
| 1272 | BitField<37, 3, TextureProcessMode> process_mode; | 1272 | BitField<37, 3, TextureProcessMode> process_mode; |
| 1273 | 1273 | ||
| 1274 | bool IsComponentEnabled(std::size_t component) const { | 1274 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1275 | return ((1ULL << component) & component_mask) != 0; | 1275 | return ((1ULL << component) & component_mask) != 0; |
| 1276 | } | 1276 | } |
| 1277 | 1277 | ||
| 1278 | TextureProcessMode GetTextureProcessMode() const { | 1278 | [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { |
| 1279 | return process_mode; | 1279 | return process_mode; |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| 1282 | bool UsesMiscMode(TextureMiscMode mode) const { | 1282 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1283 | switch (mode) { | 1283 | switch (mode) { |
| 1284 | case TextureMiscMode::DC: | 1284 | case TextureMiscMode::DC: |
| 1285 | return dc_flag != 0; | 1285 | return dc_flag != 0; |
| @@ -1299,7 +1299,7 @@ union Instruction { | |||
| 1299 | BitField<31, 4, u64> component_mask; | 1299 | BitField<31, 4, u64> component_mask; |
| 1300 | BitField<49, 1, u64> nodep_flag; | 1300 | BitField<49, 1, u64> nodep_flag; |
| 1301 | 1301 | ||
| 1302 | bool UsesMiscMode(TextureMiscMode mode) const { | 1302 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1303 | switch (mode) { | 1303 | switch (mode) { |
| 1304 | case TextureMiscMode::NODEP: | 1304 | case TextureMiscMode::NODEP: |
| 1305 | return nodep_flag != 0; | 1305 | return nodep_flag != 0; |
| @@ -1309,7 +1309,7 @@ union Instruction { | |||
| 1309 | return false; | 1309 | return false; |
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | bool IsComponentEnabled(std::size_t component) const { | 1312 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1313 | return ((1ULL << component) & component_mask) != 0; | 1313 | return ((1ULL << component) & component_mask) != 0; |
| 1314 | } | 1314 | } |
| 1315 | } txq; | 1315 | } txq; |
| @@ -1321,11 +1321,11 @@ union Instruction { | |||
| 1321 | BitField<35, 1, u64> ndv_flag; | 1321 | BitField<35, 1, u64> ndv_flag; |
| 1322 | BitField<49, 1, u64> nodep_flag; | 1322 | BitField<49, 1, u64> nodep_flag; |
| 1323 | 1323 | ||
| 1324 | bool IsComponentEnabled(std::size_t component) const { | 1324 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1325 | return ((1ull << component) & component_mask) != 0; | 1325 | return ((1ULL << component) & component_mask) != 0; |
| 1326 | } | 1326 | } |
| 1327 | 1327 | ||
| 1328 | bool UsesMiscMode(TextureMiscMode mode) const { | 1328 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1329 | switch (mode) { | 1329 | switch (mode) { |
| 1330 | case TextureMiscMode::NDV: | 1330 | case TextureMiscMode::NDV: |
| 1331 | return (ndv_flag != 0); | 1331 | return (ndv_flag != 0); |
| @@ -1347,7 +1347,7 @@ union Instruction { | |||
| 1347 | BitField<54, 2, u64> offset_mode; | 1347 | BitField<54, 2, u64> offset_mode; |
| 1348 | BitField<56, 2, u64> component; | 1348 | BitField<56, 2, u64> component; |
| 1349 | 1349 | ||
| 1350 | bool UsesMiscMode(TextureMiscMode mode) const { | 1350 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1351 | switch (mode) { | 1351 | switch (mode) { |
| 1352 | case TextureMiscMode::NDV: | 1352 | case TextureMiscMode::NDV: |
| 1353 | return ndv_flag != 0; | 1353 | return ndv_flag != 0; |
| @@ -1373,7 +1373,7 @@ union Instruction { | |||
| 1373 | BitField<33, 2, u64> offset_mode; | 1373 | BitField<33, 2, u64> offset_mode; |
| 1374 | BitField<37, 2, u64> component; | 1374 | BitField<37, 2, u64> component; |
| 1375 | 1375 | ||
| 1376 | bool UsesMiscMode(TextureMiscMode mode) const { | 1376 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1377 | switch (mode) { | 1377 | switch (mode) { |
| 1378 | case TextureMiscMode::NDV: | 1378 | case TextureMiscMode::NDV: |
| 1379 | return ndv_flag != 0; | 1379 | return ndv_flag != 0; |
| @@ -1399,7 +1399,7 @@ union Instruction { | |||
| 1399 | BitField<52, 2, u64> component; | 1399 | BitField<52, 2, u64> component; |
| 1400 | BitField<55, 1, u64> fp16_flag; | 1400 | BitField<55, 1, u64> fp16_flag; |
| 1401 | 1401 | ||
| 1402 | bool UsesMiscMode(TextureMiscMode mode) const { | 1402 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1403 | switch (mode) { | 1403 | switch (mode) { |
| 1404 | case TextureMiscMode::DC: | 1404 | case TextureMiscMode::DC: |
| 1405 | return dc_flag != 0; | 1405 | return dc_flag != 0; |
| @@ -1422,16 +1422,20 @@ union Instruction { | |||
| 1422 | BitField<53, 4, u64> texture_info; | 1422 | BitField<53, 4, u64> texture_info; |
| 1423 | BitField<59, 1, u64> fp32_flag; | 1423 | BitField<59, 1, u64> fp32_flag; |
| 1424 | 1424 | ||
| 1425 | TextureType GetTextureType() const { | 1425 | [[nodiscard]] TextureType GetTextureType() const { |
| 1426 | // The TEXS instruction has a weird encoding for the texture type. | 1426 | // The TEXS instruction has a weird encoding for the texture type. |
| 1427 | if (texture_info == 0) | 1427 | if (texture_info == 0) { |
| 1428 | return TextureType::Texture1D; | 1428 | return TextureType::Texture1D; |
| 1429 | if (texture_info >= 1 && texture_info <= 9) | 1429 | } |
| 1430 | if (texture_info >= 1 && texture_info <= 9) { | ||
| 1430 | return TextureType::Texture2D; | 1431 | return TextureType::Texture2D; |
| 1431 | if (texture_info >= 10 && texture_info <= 11) | 1432 | } |
| 1433 | if (texture_info >= 10 && texture_info <= 11) { | ||
| 1432 | return TextureType::Texture3D; | 1434 | return TextureType::Texture3D; |
| 1433 | if (texture_info >= 12 && texture_info <= 13) | 1435 | } |
| 1436 | if (texture_info >= 12 && texture_info <= 13) { | ||
| 1434 | return TextureType::TextureCube; | 1437 | return TextureType::TextureCube; |
| 1438 | } | ||
| 1435 | 1439 | ||
| 1436 | LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}", | 1440 | LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}", |
| 1437 | static_cast<u32>(texture_info.Value())); | 1441 | static_cast<u32>(texture_info.Value())); |
| @@ -1439,7 +1443,7 @@ union Instruction { | |||
| 1439 | return TextureType::Texture1D; | 1443 | return TextureType::Texture1D; |
| 1440 | } | 1444 | } |
| 1441 | 1445 | ||
| 1442 | TextureProcessMode GetTextureProcessMode() const { | 1446 | [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { |
| 1443 | switch (texture_info) { | 1447 | switch (texture_info) { |
| 1444 | case 0: | 1448 | case 0: |
| 1445 | case 2: | 1449 | case 2: |
| @@ -1458,7 +1462,7 @@ union Instruction { | |||
| 1458 | return TextureProcessMode::None; | 1462 | return TextureProcessMode::None; |
| 1459 | } | 1463 | } |
| 1460 | 1464 | ||
| 1461 | bool UsesMiscMode(TextureMiscMode mode) const { | 1465 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1462 | switch (mode) { | 1466 | switch (mode) { |
| 1463 | case TextureMiscMode::DC: | 1467 | case TextureMiscMode::DC: |
| 1464 | return (texture_info >= 4 && texture_info <= 6) || texture_info == 9; | 1468 | return (texture_info >= 4 && texture_info <= 6) || texture_info == 9; |
| @@ -1470,16 +1474,16 @@ union Instruction { | |||
| 1470 | return false; | 1474 | return false; |
| 1471 | } | 1475 | } |
| 1472 | 1476 | ||
| 1473 | bool IsArrayTexture() const { | 1477 | [[nodiscard]] bool IsArrayTexture() const { |
| 1474 | // TEXS only supports Texture2D arrays. | 1478 | // TEXS only supports Texture2D arrays. |
| 1475 | return texture_info >= 7 && texture_info <= 9; | 1479 | return texture_info >= 7 && texture_info <= 9; |
| 1476 | } | 1480 | } |
| 1477 | 1481 | ||
| 1478 | bool HasTwoDestinations() const { | 1482 | [[nodiscard]] bool HasTwoDestinations() const { |
| 1479 | return gpr28.Value() != Register::ZeroIndex; | 1483 | return gpr28.Value() != Register::ZeroIndex; |
| 1480 | } | 1484 | } |
| 1481 | 1485 | ||
| 1482 | bool IsComponentEnabled(std::size_t component) const { | 1486 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1483 | static constexpr std::array<std::array<u32, 8>, 4> mask_lut{{ | 1487 | static constexpr std::array<std::array<u32, 8>, 4> mask_lut{{ |
| 1484 | {}, | 1488 | {}, |
| 1485 | {0x1, 0x2, 0x4, 0x8, 0x3, 0x9, 0xa, 0xc}, | 1489 | {0x1, 0x2, 0x4, 0x8, 0x3, 0x9, 0xa, 0xc}, |
| @@ -1506,7 +1510,7 @@ union Instruction { | |||
| 1506 | BitField<54, 1, u64> cl; | 1510 | BitField<54, 1, u64> cl; |
| 1507 | BitField<55, 1, u64> process_mode; | 1511 | BitField<55, 1, u64> process_mode; |
| 1508 | 1512 | ||
| 1509 | TextureProcessMode GetTextureProcessMode() const { | 1513 | [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { |
| 1510 | return process_mode == 0 ? TextureProcessMode::LZ : TextureProcessMode::LL; | 1514 | return process_mode == 0 ? TextureProcessMode::LZ : TextureProcessMode::LL; |
| 1511 | } | 1515 | } |
| 1512 | } tld; | 1516 | } tld; |
| @@ -1516,7 +1520,7 @@ union Instruction { | |||
| 1516 | BitField<53, 4, u64> texture_info; | 1520 | BitField<53, 4, u64> texture_info; |
| 1517 | BitField<59, 1, u64> fp32_flag; | 1521 | BitField<59, 1, u64> fp32_flag; |
| 1518 | 1522 | ||
| 1519 | TextureType GetTextureType() const { | 1523 | [[nodiscard]] TextureType GetTextureType() const { |
| 1520 | // The TLDS instruction has a weird encoding for the texture type. | 1524 | // The TLDS instruction has a weird encoding for the texture type. |
| 1521 | if (texture_info <= 1) { | 1525 | if (texture_info <= 1) { |
| 1522 | return TextureType::Texture1D; | 1526 | return TextureType::Texture1D; |
| @@ -1535,13 +1539,14 @@ union Instruction { | |||
| 1535 | return TextureType::Texture1D; | 1539 | return TextureType::Texture1D; |
| 1536 | } | 1540 | } |
| 1537 | 1541 | ||
| 1538 | TextureProcessMode GetTextureProcessMode() const { | 1542 | [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { |
| 1539 | if (texture_info == 1 || texture_info == 5 || texture_info == 12) | 1543 | if (texture_info == 1 || texture_info == 5 || texture_info == 12) { |
| 1540 | return TextureProcessMode::LL; | 1544 | return TextureProcessMode::LL; |
| 1545 | } | ||
| 1541 | return TextureProcessMode::LZ; | 1546 | return TextureProcessMode::LZ; |
| 1542 | } | 1547 | } |
| 1543 | 1548 | ||
| 1544 | bool UsesMiscMode(TextureMiscMode mode) const { | 1549 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1545 | switch (mode) { | 1550 | switch (mode) { |
| 1546 | case TextureMiscMode::AOFFI: | 1551 | case TextureMiscMode::AOFFI: |
| 1547 | return texture_info == 12 || texture_info == 4; | 1552 | return texture_info == 12 || texture_info == 4; |
| @@ -1555,7 +1560,7 @@ union Instruction { | |||
| 1555 | return false; | 1560 | return false; |
| 1556 | } | 1561 | } |
| 1557 | 1562 | ||
| 1558 | bool IsArrayTexture() const { | 1563 | [[nodiscard]] bool IsArrayTexture() const { |
| 1559 | // TEXS only supports Texture2D arrays. | 1564 | // TEXS only supports Texture2D arrays. |
| 1560 | return texture_info == 8; | 1565 | return texture_info == 8; |
| 1561 | } | 1566 | } |
| @@ -1567,7 +1572,7 @@ union Instruction { | |||
| 1567 | BitField<35, 1, u64> aoffi_flag; | 1572 | BitField<35, 1, u64> aoffi_flag; |
| 1568 | BitField<49, 1, u64> nodep_flag; | 1573 | BitField<49, 1, u64> nodep_flag; |
| 1569 | 1574 | ||
| 1570 | bool UsesMiscMode(TextureMiscMode mode) const { | 1575 | [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { |
| 1571 | switch (mode) { | 1576 | switch (mode) { |
| 1572 | case TextureMiscMode::AOFFI: | 1577 | case TextureMiscMode::AOFFI: |
| 1573 | return aoffi_flag != 0; | 1578 | return aoffi_flag != 0; |
| @@ -1591,7 +1596,7 @@ union Instruction { | |||
| 1591 | BitField<20, 3, StoreType> store_data_layout; | 1596 | BitField<20, 3, StoreType> store_data_layout; |
| 1592 | BitField<20, 4, u64> component_mask_selector; | 1597 | BitField<20, 4, u64> component_mask_selector; |
| 1593 | 1598 | ||
| 1594 | bool IsComponentEnabled(std::size_t component) const { | 1599 | [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { |
| 1595 | ASSERT(mode == SurfaceDataMode::P); | 1600 | ASSERT(mode == SurfaceDataMode::P); |
| 1596 | constexpr u8 R = 0b0001; | 1601 | constexpr u8 R = 0b0001; |
| 1597 | constexpr u8 G = 0b0010; | 1602 | constexpr u8 G = 0b0010; |
| @@ -1604,7 +1609,7 @@ union Instruction { | |||
| 1604 | return std::bitset<4>{mask.at(component_mask_selector)}.test(component); | 1609 | return std::bitset<4>{mask.at(component_mask_selector)}.test(component); |
| 1605 | } | 1610 | } |
| 1606 | 1611 | ||
| 1607 | StoreType GetStoreDataLayout() const { | 1612 | [[nodiscard]] StoreType GetStoreDataLayout() const { |
| 1608 | ASSERT(mode == SurfaceDataMode::D_BA); | 1613 | ASSERT(mode == SurfaceDataMode::D_BA); |
| 1609 | return store_data_layout; | 1614 | return store_data_layout; |
| 1610 | } | 1615 | } |
| @@ -1622,14 +1627,15 @@ union Instruction { | |||
| 1622 | BitField<20, 24, u64> target; | 1627 | BitField<20, 24, u64> target; |
| 1623 | BitField<5, 1, u64> constant_buffer; | 1628 | BitField<5, 1, u64> constant_buffer; |
| 1624 | 1629 | ||
| 1625 | s32 GetBranchTarget() const { | 1630 | [[nodiscard]] s32 GetBranchTarget() const { |
| 1626 | // Sign extend the branch target offset | 1631 | // Sign extend the branch target offset |
| 1627 | u32 mask = 1U << (24 - 1); | 1632 | const auto mask = 1U << (24 - 1); |
| 1628 | u32 value = static_cast<u32>(target); | 1633 | const auto target_value = static_cast<u32>(target); |
| 1634 | constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction)); | ||
| 1635 | |||
| 1629 | // The branch offset is relative to the next instruction and is stored in bytes, so | 1636 | // The branch offset is relative to the next instruction and is stored in bytes, so |
| 1630 | // divide it by the size of an instruction and add 1 to it. | 1637 | // divide it by the size of an instruction and add 1 to it. |
| 1631 | return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) + | 1638 | return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1; |
| 1632 | 1; | ||
| 1633 | } | 1639 | } |
| 1634 | } bra; | 1640 | } bra; |
| 1635 | 1641 | ||
| @@ -1637,14 +1643,15 @@ union Instruction { | |||
| 1637 | BitField<20, 24, u64> target; | 1643 | BitField<20, 24, u64> target; |
| 1638 | BitField<5, 1, u64> constant_buffer; | 1644 | BitField<5, 1, u64> constant_buffer; |
| 1639 | 1645 | ||
| 1640 | s32 GetBranchExtend() const { | 1646 | [[nodiscard]] s32 GetBranchExtend() const { |
| 1641 | // Sign extend the branch target offset | 1647 | // Sign extend the branch target offset |
| 1642 | u32 mask = 1U << (24 - 1); | 1648 | const auto mask = 1U << (24 - 1); |
| 1643 | u32 value = static_cast<u32>(target); | 1649 | const auto target_value = static_cast<u32>(target); |
| 1650 | constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction)); | ||
| 1651 | |||
| 1644 | // The branch offset is relative to the next instruction and is stored in bytes, so | 1652 | // The branch offset is relative to the next instruction and is stored in bytes, so |
| 1645 | // divide it by the size of an instruction and add 1 to it. | 1653 | // divide it by the size of an instruction and add 1 to it. |
| 1646 | return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) + | 1654 | return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1; |
| 1647 | 1; | ||
| 1648 | } | 1655 | } |
| 1649 | } brx; | 1656 | } brx; |
| 1650 | 1657 | ||
| @@ -1697,7 +1704,7 @@ union Instruction { | |||
| 1697 | BitField<50, 1, u64> is_op_b_register; | 1704 | BitField<50, 1, u64> is_op_b_register; |
| 1698 | BitField<51, 3, VmnmxOperation> operation; | 1705 | BitField<51, 3, VmnmxOperation> operation; |
| 1699 | 1706 | ||
| 1700 | VmnmxType SourceFormatA() const { | 1707 | [[nodiscard]] VmnmxType SourceFormatA() const { |
| 1701 | switch (src_format_a) { | 1708 | switch (src_format_a) { |
| 1702 | case 0b11: | 1709 | case 0b11: |
| 1703 | return VmnmxType::Bits32; | 1710 | return VmnmxType::Bits32; |
| @@ -1708,7 +1715,7 @@ union Instruction { | |||
| 1708 | } | 1715 | } |
| 1709 | } | 1716 | } |
| 1710 | 1717 | ||
| 1711 | VmnmxType SourceFormatB() const { | 1718 | [[nodiscard]] VmnmxType SourceFormatB() const { |
| 1712 | switch (src_format_b) { | 1719 | switch (src_format_b) { |
| 1713 | case 0b11: | 1720 | case 0b11: |
| 1714 | return VmnmxType::Bits32; | 1721 | return VmnmxType::Bits32; |
| @@ -1739,7 +1746,7 @@ union Instruction { | |||
| 1739 | BitField<20, 14, u64> shifted_offset; | 1746 | BitField<20, 14, u64> shifted_offset; |
| 1740 | BitField<34, 5, u64> index; | 1747 | BitField<34, 5, u64> index; |
| 1741 | 1748 | ||
| 1742 | u64 GetOffset() const { | 1749 | [[nodiscard]] u64 GetOffset() const { |
| 1743 | return shifted_offset * 4; | 1750 | return shifted_offset * 4; |
| 1744 | } | 1751 | } |
| 1745 | } cbuf34; | 1752 | } cbuf34; |
| @@ -1748,7 +1755,7 @@ union Instruction { | |||
| 1748 | BitField<20, 16, s64> offset; | 1755 | BitField<20, 16, s64> offset; |
| 1749 | BitField<36, 5, u64> index; | 1756 | BitField<36, 5, u64> index; |
| 1750 | 1757 | ||
| 1751 | s64 GetOffset() const { | 1758 | [[nodiscard]] s64 GetOffset() const { |
| 1752 | return offset; | 1759 | return offset; |
| 1753 | } | 1760 | } |
| 1754 | } cbuf36; | 1761 | } cbuf36; |
| @@ -1997,29 +2004,29 @@ public: | |||
| 1997 | 2004 | ||
| 1998 | /// Returns whether an opcode has an execution predicate field or not (ie, whether it can be | 2005 | /// Returns whether an opcode has an execution predicate field or not (ie, whether it can be |
| 1999 | /// conditionally executed). | 2006 | /// conditionally executed). |
| 2000 | static bool IsPredicatedInstruction(Id opcode) { | 2007 | [[nodiscard]] static bool IsPredicatedInstruction(Id opcode) { |
| 2001 | // TODO(Subv): Add the rest of unpredicated instructions. | 2008 | // TODO(Subv): Add the rest of unpredicated instructions. |
| 2002 | return opcode != Id::SSY && opcode != Id::PBK; | 2009 | return opcode != Id::SSY && opcode != Id::PBK; |
| 2003 | } | 2010 | } |
| 2004 | 2011 | ||
| 2005 | class Matcher { | 2012 | class Matcher { |
| 2006 | public: | 2013 | public: |
| 2007 | constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type) | 2014 | constexpr Matcher(const char* const name_, u16 mask_, u16 expected_, Id id_, Type type_) |
| 2008 | : name{name}, mask{mask}, expected{expected}, id{id}, type{type} {} | 2015 | : name{name_}, mask{mask_}, expected{expected_}, id{id_}, type{type_} {} |
| 2009 | 2016 | ||
| 2010 | constexpr const char* GetName() const { | 2017 | [[nodiscard]] constexpr const char* GetName() const { |
| 2011 | return name; | 2018 | return name; |
| 2012 | } | 2019 | } |
| 2013 | 2020 | ||
| 2014 | constexpr u16 GetMask() const { | 2021 | [[nodiscard]] constexpr u16 GetMask() const { |
| 2015 | return mask; | 2022 | return mask; |
| 2016 | } | 2023 | } |
| 2017 | 2024 | ||
| 2018 | constexpr Id GetId() const { | 2025 | [[nodiscard]] constexpr Id GetId() const { |
| 2019 | return id; | 2026 | return id; |
| 2020 | } | 2027 | } |
| 2021 | 2028 | ||
| 2022 | constexpr Type GetType() const { | 2029 | [[nodiscard]] constexpr Type GetType() const { |
| 2023 | return type; | 2030 | return type; |
| 2024 | } | 2031 | } |
| 2025 | 2032 | ||
| @@ -2028,7 +2035,7 @@ public: | |||
| 2028 | * @param instruction The instruction to test | 2035 | * @param instruction The instruction to test |
| 2029 | * @returns true if the given instruction matches. | 2036 | * @returns true if the given instruction matches. |
| 2030 | */ | 2037 | */ |
| 2031 | constexpr bool Matches(u16 instruction) const { | 2038 | [[nodiscard]] constexpr bool Matches(u16 instruction) const { |
| 2032 | return (instruction & mask) == expected; | 2039 | return (instruction & mask) == expected; |
| 2033 | } | 2040 | } |
| 2034 | 2041 | ||
| @@ -2040,7 +2047,8 @@ public: | |||
| 2040 | Type type; | 2047 | Type type; |
| 2041 | }; | 2048 | }; |
| 2042 | 2049 | ||
| 2043 | static std::optional<std::reference_wrapper<const Matcher>> Decode(Instruction instr) { | 2050 | using DecodeResult = std::optional<std::reference_wrapper<const Matcher>>; |
| 2051 | [[nodiscard]] static DecodeResult Decode(Instruction instr) { | ||
| 2044 | static const auto table{GetDecodeTable()}; | 2052 | static const auto table{GetDecodeTable()}; |
| 2045 | 2053 | ||
| 2046 | const auto matches_instruction = [instr](const auto& matcher) { | 2054 | const auto matches_instruction = [instr](const auto& matcher) { |
| @@ -2062,7 +2070,7 @@ private: | |||
| 2062 | * A '0' in a bitstring indicates that a zero must be present at that bit position. | 2070 | * A '0' in a bitstring indicates that a zero must be present at that bit position. |
| 2063 | * A '1' in a bitstring indicates that a one must be present at that bit position. | 2071 | * A '1' in a bitstring indicates that a one must be present at that bit position. |
| 2064 | */ | 2072 | */ |
| 2065 | static constexpr auto GetMaskAndExpect(const char* const bitstring) { | 2073 | [[nodiscard]] static constexpr auto GetMaskAndExpect(const char* const bitstring) { |
| 2066 | u16 mask = 0, expect = 0; | 2074 | u16 mask = 0, expect = 0; |
| 2067 | for (std::size_t i = 0; i < opcode_bitsize; i++) { | 2075 | for (std::size_t i = 0; i < opcode_bitsize; i++) { |
| 2068 | const std::size_t bit_position = opcode_bitsize - i - 1; | 2076 | const std::size_t bit_position = opcode_bitsize - i - 1; |
| @@ -2084,14 +2092,14 @@ private: | |||
| 2084 | 2092 | ||
| 2085 | public: | 2093 | public: |
| 2086 | /// Creates a matcher that can match and parse instructions based on bitstring. | 2094 | /// Creates a matcher that can match and parse instructions based on bitstring. |
| 2087 | static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type, | 2095 | [[nodiscard]] static constexpr auto GetMatcher(const char* const bitstring, Id op, |
| 2088 | const char* const name) { | 2096 | Type type, const char* const name) { |
| 2089 | const auto [mask, expected] = GetMaskAndExpect(bitstring); | 2097 | const auto [mask, expected] = GetMaskAndExpect(bitstring); |
| 2090 | return Matcher(name, mask, expected, op, type); | 2098 | return Matcher(name, mask, expected, op, type); |
| 2091 | } | 2099 | } |
| 2092 | }; | 2100 | }; |
| 2093 | 2101 | ||
| 2094 | static std::vector<Matcher> GetDecodeTable() { | 2102 | [[nodiscard]] static std::vector<Matcher> GetDecodeTable() { |
| 2095 | std::vector<Matcher> table = { | 2103 | std::vector<Matcher> table = { |
| 2096 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) | 2104 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) |
| 2097 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), | 2105 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index cf5235a79..21410e125 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -17,11 +17,11 @@ | |||
| 17 | #include "video_core/dma_pusher.h" | 17 | #include "video_core/dma_pusher.h" |
| 18 | 18 | ||
| 19 | using CacheAddr = std::uintptr_t; | 19 | using CacheAddr = std::uintptr_t; |
| 20 | inline CacheAddr ToCacheAddr(const void* host_ptr) { | 20 | [[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) { |
| 21 | return reinterpret_cast<CacheAddr>(host_ptr); | 21 | return reinterpret_cast<CacheAddr>(host_ptr); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | inline u8* FromCacheAddr(CacheAddr cache_addr) { | 24 | [[nodiscard]] inline u8* FromCacheAddr(CacheAddr cache_addr) { |
| 25 | return reinterpret_cast<u8*>(cache_addr); | 25 | return reinterpret_cast<u8*>(cache_addr); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| @@ -149,13 +149,13 @@ public: | |||
| 149 | u32 subchannel{}; | 149 | u32 subchannel{}; |
| 150 | u32 method_count{}; | 150 | u32 method_count{}; |
| 151 | 151 | ||
| 152 | bool IsLastCall() const { | ||
| 153 | return method_count <= 1; | ||
| 154 | } | ||
| 155 | |||
| 156 | MethodCall(u32 method, u32 argument, u32 subchannel = 0, u32 method_count = 0) | 152 | MethodCall(u32 method, u32 argument, u32 subchannel = 0, u32 method_count = 0) |
| 157 | : method(method), argument(argument), subchannel(subchannel), | 153 | : method(method), argument(argument), subchannel(subchannel), |
| 158 | method_count(method_count) {} | 154 | method_count(method_count) {} |
| 155 | |||
| 156 | [[nodiscard]] bool IsLastCall() const { | ||
| 157 | return method_count <= 1; | ||
| 158 | } | ||
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | explicit GPU(Core::System& system, bool is_async, bool use_nvdec); | 161 | explicit GPU(Core::System& system, bool is_async, bool use_nvdec); |
| @@ -179,10 +179,10 @@ public: | |||
| 179 | virtual void OnCommandListEnd(); | 179 | virtual void OnCommandListEnd(); |
| 180 | 180 | ||
| 181 | /// Request a host GPU memory flush from the CPU. | 181 | /// Request a host GPU memory flush from the CPU. |
| 182 | u64 RequestFlush(VAddr addr, std::size_t size); | 182 | [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size); |
| 183 | 183 | ||
| 184 | /// Obtains current flush request fence id. | 184 | /// Obtains current flush request fence id. |
| 185 | u64 CurrentFlushRequestFence() const { | 185 | [[nodiscard]] u64 CurrentFlushRequestFence() const { |
| 186 | return current_flush_fence.load(std::memory_order_relaxed); | 186 | return current_flush_fence.load(std::memory_order_relaxed); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| @@ -190,48 +190,52 @@ public: | |||
| 190 | void TickWork(); | 190 | void TickWork(); |
| 191 | 191 | ||
| 192 | /// Returns a reference to the Maxwell3D GPU engine. | 192 | /// Returns a reference to the Maxwell3D GPU engine. |
| 193 | Engines::Maxwell3D& Maxwell3D(); | 193 | [[nodiscard]] Engines::Maxwell3D& Maxwell3D(); |
| 194 | 194 | ||
| 195 | /// Returns a const reference to the Maxwell3D GPU engine. | 195 | /// Returns a const reference to the Maxwell3D GPU engine. |
| 196 | const Engines::Maxwell3D& Maxwell3D() const; | 196 | [[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const; |
| 197 | 197 | ||
| 198 | /// Returns a reference to the KeplerCompute GPU engine. | 198 | /// Returns a reference to the KeplerCompute GPU engine. |
| 199 | Engines::KeplerCompute& KeplerCompute(); | 199 | [[nodiscard]] Engines::KeplerCompute& KeplerCompute(); |
| 200 | 200 | ||
| 201 | /// Returns a reference to the KeplerCompute GPU engine. | 201 | /// Returns a reference to the KeplerCompute GPU engine. |
| 202 | const Engines::KeplerCompute& KeplerCompute() const; | 202 | [[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const; |
| 203 | 203 | ||
| 204 | /// Returns a reference to the GPU memory manager. | 204 | /// Returns a reference to the GPU memory manager. |
| 205 | Tegra::MemoryManager& MemoryManager(); | 205 | [[nodiscard]] Tegra::MemoryManager& MemoryManager(); |
| 206 | 206 | ||
| 207 | /// Returns a const reference to the GPU memory manager. | 207 | /// Returns a const reference to the GPU memory manager. |
| 208 | const Tegra::MemoryManager& MemoryManager() const; | 208 | [[nodiscard]] const Tegra::MemoryManager& MemoryManager() const; |
| 209 | 209 | ||
| 210 | /// Returns a reference to the GPU DMA pusher. | 210 | /// Returns a reference to the GPU DMA pusher. |
| 211 | Tegra::DmaPusher& DmaPusher(); | 211 | [[nodiscard]] Tegra::DmaPusher& DmaPusher(); |
| 212 | 212 | ||
| 213 | /// Returns a const reference to the GPU DMA pusher. | 213 | /// Returns a const reference to the GPU DMA pusher. |
| 214 | const Tegra::DmaPusher& DmaPusher() const; | 214 | [[nodiscard]] const Tegra::DmaPusher& DmaPusher() const; |
| 215 | 215 | ||
| 216 | /// Returns a reference to the GPU CDMA pusher. | 216 | /// Returns a reference to the GPU CDMA pusher. |
| 217 | Tegra::CDmaPusher& CDmaPusher(); | 217 | [[nodiscard]] Tegra::CDmaPusher& CDmaPusher(); |
| 218 | 218 | ||
| 219 | /// Returns a const reference to the GPU CDMA pusher. | 219 | /// Returns a const reference to the GPU CDMA pusher. |
| 220 | const Tegra::CDmaPusher& CDmaPusher() const; | 220 | [[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const; |
| 221 | 221 | ||
| 222 | VideoCore::RendererBase& Renderer() { | 222 | /// Returns a reference to the underlying renderer. |
| 223 | [[nodiscard]] VideoCore::RendererBase& Renderer() { | ||
| 223 | return *renderer; | 224 | return *renderer; |
| 224 | } | 225 | } |
| 225 | 226 | ||
| 226 | const VideoCore::RendererBase& Renderer() const { | 227 | /// Returns a const reference to the underlying renderer. |
| 228 | [[nodiscard]] const VideoCore::RendererBase& Renderer() const { | ||
| 227 | return *renderer; | 229 | return *renderer; |
| 228 | } | 230 | } |
| 229 | 231 | ||
| 230 | VideoCore::ShaderNotify& ShaderNotify() { | 232 | /// Returns a reference to the shader notifier. |
| 233 | [[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() { | ||
| 231 | return *shader_notify; | 234 | return *shader_notify; |
| 232 | } | 235 | } |
| 233 | 236 | ||
| 234 | const VideoCore::ShaderNotify& ShaderNotify() const { | 237 | /// Returns a const reference to the shader notifier. |
| 238 | [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const { | ||
| 235 | return *shader_notify; | 239 | return *shader_notify; |
| 236 | } | 240 | } |
| 237 | 241 | ||
| @@ -243,23 +247,23 @@ public: | |||
| 243 | 247 | ||
| 244 | void IncrementSyncPoint(u32 syncpoint_id); | 248 | void IncrementSyncPoint(u32 syncpoint_id); |
| 245 | 249 | ||
| 246 | u32 GetSyncpointValue(u32 syncpoint_id) const; | 250 | [[nodiscard]] u32 GetSyncpointValue(u32 syncpoint_id) const; |
| 247 | 251 | ||
| 248 | void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value); | 252 | void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value); |
| 249 | 253 | ||
| 250 | bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value); | 254 | [[nodiscard]] bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value); |
| 251 | 255 | ||
| 252 | u64 GetTicks() const; | 256 | [[nodiscard]] u64 GetTicks() const; |
| 253 | 257 | ||
| 254 | std::unique_lock<std::mutex> LockSync() { | 258 | [[nodiscard]] std::unique_lock<std::mutex> LockSync() { |
| 255 | return std::unique_lock{sync_mutex}; | 259 | return std::unique_lock{sync_mutex}; |
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | bool IsAsync() const { | 262 | [[nodiscard]] bool IsAsync() const { |
| 259 | return is_async; | 263 | return is_async; |
| 260 | } | 264 | } |
| 261 | 265 | ||
| 262 | bool UseNvdec() const { | 266 | [[nodiscard]] bool UseNvdec() const { |
| 263 | return use_nvdec; | 267 | return use_nvdec; |
| 264 | } | 268 | } |
| 265 | 269 | ||
| @@ -273,7 +277,7 @@ public: | |||
| 273 | BitField<0, 1, FenceOperation> op; | 277 | BitField<0, 1, FenceOperation> op; |
| 274 | BitField<8, 24, u32> syncpoint_id; | 278 | BitField<8, 24, u32> syncpoint_id; |
| 275 | 279 | ||
| 276 | static CommandHeader Build(FenceOperation op, u32 syncpoint_id) { | 280 | [[nodiscard]] static CommandHeader Build(FenceOperation op, u32 syncpoint_id) { |
| 277 | FenceAction result{}; | 281 | FenceAction result{}; |
| 278 | result.op.Assign(op); | 282 | result.op.Assign(op); |
| 279 | result.syncpoint_id.Assign(syncpoint_id); | 283 | result.syncpoint_id.Assign(syncpoint_id); |
| @@ -291,7 +295,7 @@ public: | |||
| 291 | u32 address_high; | 295 | u32 address_high; |
| 292 | u32 address_low; | 296 | u32 address_low; |
| 293 | 297 | ||
| 294 | GPUVAddr SemaphoreAddress() const { | 298 | [[nodiscard]] GPUVAddr SemaphoreAddress() const { |
| 295 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | | 299 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | |
| 296 | address_low); | 300 | address_low); |
| 297 | } | 301 | } |
| @@ -374,7 +378,7 @@ private: | |||
| 374 | u32 methods_pending); | 378 | u32 methods_pending); |
| 375 | 379 | ||
| 376 | /// Determines where the method should be executed. | 380 | /// Determines where the method should be executed. |
| 377 | bool ExecuteMethodOnEngine(u32 method); | 381 | [[nodiscard]] bool ExecuteMethodOnEngine(u32 method); |
| 378 | 382 | ||
| 379 | protected: | 383 | protected: |
| 380 | Core::System& system; | 384 | Core::System& system; |
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index b3e0919f8..27ef4c69a 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -32,7 +32,7 @@ using DiskResourceLoadCallback = std::function<void(LoadCallbackStage, std::size | |||
| 32 | 32 | ||
| 33 | class RasterizerInterface { | 33 | class RasterizerInterface { |
| 34 | public: | 34 | public: |
| 35 | virtual ~RasterizerInterface() {} | 35 | virtual ~RasterizerInterface() = default; |
| 36 | 36 | ||
| 37 | /// Dispatches a draw invocation | 37 | /// Dispatches a draw invocation |
| 38 | virtual void Draw(bool is_indexed, bool is_instanced) = 0; | 38 | virtual void Draw(bool is_indexed, bool is_instanced) = 0; |
| @@ -90,15 +90,16 @@ public: | |||
| 90 | virtual void TickFrame() = 0; | 90 | virtual void TickFrame() = 0; |
| 91 | 91 | ||
| 92 | /// Attempt to use a faster method to perform a surface copy | 92 | /// Attempt to use a faster method to perform a surface copy |
| 93 | virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, | 93 | [[nodiscard]] virtual bool AccelerateSurfaceCopy( |
| 94 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, | 94 | const Tegra::Engines::Fermi2D::Regs::Surface& src, |
| 95 | const Tegra::Engines::Fermi2D::Config& copy_config) { | 95 | const Tegra::Engines::Fermi2D::Regs::Surface& dst, |
| 96 | const Tegra::Engines::Fermi2D::Config& copy_config) { | ||
| 96 | return false; | 97 | return false; |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | /// Attempt to use a faster method to display the framebuffer to screen | 100 | /// Attempt to use a faster method to display the framebuffer to screen |
| 100 | virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 101 | [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 101 | u32 pixel_stride) { | 102 | VAddr framebuffer_addr, u32 pixel_stride) { |
| 102 | return false; | 103 | return false; |
| 103 | } | 104 | } |
| 104 | 105 | ||
| @@ -110,12 +111,12 @@ public: | |||
| 110 | const DiskResourceLoadCallback& callback) {} | 111 | const DiskResourceLoadCallback& callback) {} |
| 111 | 112 | ||
| 112 | /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. | 113 | /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. |
| 113 | GuestDriverProfile& AccessGuestDriverProfile() { | 114 | [[nodiscard]] GuestDriverProfile& AccessGuestDriverProfile() { |
| 114 | return guest_driver_profile; | 115 | return guest_driver_profile; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. | 118 | /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. |
| 118 | const GuestDriverProfile& AccessGuestDriverProfile() const { | 119 | [[nodiscard]] const GuestDriverProfile& AccessGuestDriverProfile() const { |
| 119 | return guest_driver_profile; | 120 | return guest_driver_profile; |
| 120 | } | 121 | } |
| 121 | 122 | ||
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 5c650808b..51dde8eb5 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -38,7 +38,7 @@ public: | |||
| 38 | virtual ~RendererBase(); | 38 | virtual ~RendererBase(); |
| 39 | 39 | ||
| 40 | /// Initialize the renderer | 40 | /// Initialize the renderer |
| 41 | virtual bool Init() = 0; | 41 | [[nodiscard]] virtual bool Init() = 0; |
| 42 | 42 | ||
| 43 | /// Shutdown the renderer | 43 | /// Shutdown the renderer |
| 44 | virtual void ShutDown() = 0; | 44 | virtual void ShutDown() = 0; |
| @@ -49,43 +49,43 @@ public: | |||
| 49 | // Getter/setter functions: | 49 | // Getter/setter functions: |
| 50 | // ------------------------ | 50 | // ------------------------ |
| 51 | 51 | ||
| 52 | f32 GetCurrentFPS() const { | 52 | [[nodiscard]] f32 GetCurrentFPS() const { |
| 53 | return m_current_fps; | 53 | return m_current_fps; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | int GetCurrentFrame() const { | 56 | [[nodiscard]] int GetCurrentFrame() const { |
| 57 | return m_current_frame; | 57 | return m_current_frame; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | RasterizerInterface& Rasterizer() { | 60 | [[nodiscard]] RasterizerInterface& Rasterizer() { |
| 61 | return *rasterizer; | 61 | return *rasterizer; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | const RasterizerInterface& Rasterizer() const { | 64 | [[nodiscard]] const RasterizerInterface& Rasterizer() const { |
| 65 | return *rasterizer; | 65 | return *rasterizer; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | Core::Frontend::GraphicsContext& Context() { | 68 | [[nodiscard]] Core::Frontend::GraphicsContext& Context() { |
| 69 | return *context; | 69 | return *context; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | const Core::Frontend::GraphicsContext& Context() const { | 72 | [[nodiscard]] const Core::Frontend::GraphicsContext& Context() const { |
| 73 | return *context; | 73 | return *context; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | Core::Frontend::EmuWindow& GetRenderWindow() { | 76 | [[nodiscard]] Core::Frontend::EmuWindow& GetRenderWindow() { |
| 77 | return render_window; | 77 | return render_window; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | const Core::Frontend::EmuWindow& GetRenderWindow() const { | 80 | [[nodiscard]] const Core::Frontend::EmuWindow& GetRenderWindow() const { |
| 81 | return render_window; | 81 | return render_window; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | RendererSettings& Settings() { | 84 | [[nodiscard]] RendererSettings& Settings() { |
| 85 | return renderer_settings; | 85 | return renderer_settings; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | const RendererSettings& Settings() const { | 88 | [[nodiscard]] const RendererSettings& Settings() const { |
| 89 | return renderer_settings; | 89 | return renderer_settings; |
| 90 | } | 90 | } |
| 91 | 91 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 36bf92808..cfddbde5d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -1156,7 +1156,7 @@ void RasterizerOpenGL::SyncViewport() { | |||
| 1156 | flags[Dirty::ClipControl] = false; | 1156 | flags[Dirty::ClipControl] = false; |
| 1157 | 1157 | ||
| 1158 | bool flip_y = false; | 1158 | bool flip_y = false; |
| 1159 | if (regs.viewport_transform[0].scale_y < 0.0) { | 1159 | if (regs.viewport_transform[0].scale_y < 0.0f) { |
| 1160 | flip_y = !flip_y; | 1160 | flip_y = !flip_y; |
| 1161 | } | 1161 | } |
| 1162 | if (regs.screen_y_control.y_negate != 0) { | 1162 | if (regs.screen_y_control.y_negate != 0) { |
| @@ -1579,10 +1579,6 @@ void RasterizerOpenGL::SyncAlphaTest() { | |||
| 1579 | flags[Dirty::AlphaTest] = false; | 1579 | flags[Dirty::AlphaTest] = false; |
| 1580 | 1580 | ||
| 1581 | const auto& regs = maxwell3d.regs; | 1581 | const auto& regs = maxwell3d.regs; |
| 1582 | if (regs.alpha_test_enabled && regs.rt_control.count > 1) { | ||
| 1583 | LOG_WARNING(Render_OpenGL, "Alpha testing with more than one render target is not tested"); | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | if (regs.alpha_test_enabled) { | 1582 | if (regs.alpha_test_enabled) { |
| 1587 | glEnable(GL_ALPHA_TEST); | 1583 | glEnable(GL_ALPHA_TEST); |
| 1588 | glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref); | 1584 | glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref); |
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp index 39cc3b869..6920afdf2 100644 --- a/src/video_core/shader/async_shaders.cpp +++ b/src/video_core/shader/async_shaders.cpp | |||
| @@ -43,8 +43,8 @@ void AsyncShaders::AllocateWorkers() { | |||
| 43 | // Create workers | 43 | // Create workers |
| 44 | for (std::size_t i = 0; i < num_workers; i++) { | 44 | for (std::size_t i = 0; i < num_workers; i++) { |
| 45 | context_list.push_back(emu_window.CreateSharedContext()); | 45 | context_list.push_back(emu_window.CreateSharedContext()); |
| 46 | worker_threads.push_back( | 46 | worker_threads.emplace_back(&AsyncShaders::ShaderCompilerThread, this, |
| 47 | std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get())); | 47 | context_list[i].get()); |
| 48 | } | 48 | } |
| 49 | } | 49 | } |
| 50 | 50 | ||
| @@ -106,8 +106,7 @@ std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() { | |||
| 106 | std::vector<Result> results; | 106 | std::vector<Result> results; |
| 107 | { | 107 | { |
| 108 | std::unique_lock lock{completed_mutex}; | 108 | std::unique_lock lock{completed_mutex}; |
| 109 | results.assign(std::make_move_iterator(finished_work.begin()), | 109 | results = std::move(finished_work); |
| 110 | std::make_move_iterator(finished_work.end())); | ||
| 111 | finished_work.clear(); | 110 | finished_work.clear(); |
| 112 | } | 111 | } |
| 113 | return results; | 112 | return results; |
| @@ -116,11 +115,10 @@ std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() { | |||
| 116 | void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, | 115 | void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, |
| 117 | Tegra::Engines::ShaderType shader_type, u64 uid, | 116 | Tegra::Engines::ShaderType shader_type, u64 uid, |
| 118 | std::vector<u64> code, std::vector<u64> code_b, | 117 | std::vector<u64> code, std::vector<u64> code_b, |
| 119 | u32 main_offset, | 118 | u32 main_offset, CompilerSettings compiler_settings, |
| 120 | VideoCommon::Shader::CompilerSettings compiler_settings, | 119 | const Registry& registry, VAddr cpu_addr) { |
| 121 | const VideoCommon::Shader::Registry& registry, | 120 | std::unique_lock lock(queue_mutex); |
| 122 | VAddr cpu_addr) { | 121 | pending_queue.push({ |
| 123 | WorkerParams params{ | ||
| 124 | .backend = device.UseAssemblyShaders() ? Backend::GLASM : Backend::OpenGL, | 122 | .backend = device.UseAssemblyShaders() ? Backend::GLASM : Backend::OpenGL, |
| 125 | .device = &device, | 123 | .device = &device, |
| 126 | .shader_type = shader_type, | 124 | .shader_type = shader_type, |
| @@ -131,9 +129,7 @@ void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, | |||
| 131 | .compiler_settings = compiler_settings, | 129 | .compiler_settings = compiler_settings, |
| 132 | .registry = registry, | 130 | .registry = registry, |
| 133 | .cpu_address = cpu_addr, | 131 | .cpu_address = cpu_addr, |
| 134 | }; | 132 | }); |
| 135 | std::unique_lock lock(queue_mutex); | ||
| 136 | pending_queue.push(std::move(params)); | ||
| 137 | cv.notify_one(); | 133 | cv.notify_one(); |
| 138 | } | 134 | } |
| 139 | 135 | ||
| @@ -145,7 +141,8 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, | |||
| 145 | std::vector<VkDescriptorSetLayoutBinding> bindings, | 141 | std::vector<VkDescriptorSetLayoutBinding> bindings, |
| 146 | Vulkan::SPIRVProgram program, | 142 | Vulkan::SPIRVProgram program, |
| 147 | Vulkan::GraphicsPipelineCacheKey key) { | 143 | Vulkan::GraphicsPipelineCacheKey key) { |
| 148 | WorkerParams params{ | 144 | std::unique_lock lock(queue_mutex); |
| 145 | pending_queue.push({ | ||
| 149 | .backend = Backend::Vulkan, | 146 | .backend = Backend::Vulkan, |
| 150 | .pp_cache = pp_cache, | 147 | .pp_cache = pp_cache, |
| 151 | .vk_device = &device, | 148 | .vk_device = &device, |
| @@ -153,13 +150,10 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, | |||
| 153 | .descriptor_pool = &descriptor_pool, | 150 | .descriptor_pool = &descriptor_pool, |
| 154 | .update_descriptor_queue = &update_descriptor_queue, | 151 | .update_descriptor_queue = &update_descriptor_queue, |
| 155 | .renderpass_cache = &renderpass_cache, | 152 | .renderpass_cache = &renderpass_cache, |
| 156 | .bindings = bindings, | 153 | .bindings = std::move(bindings), |
| 157 | .program = program, | 154 | .program = std::move(program), |
| 158 | .key = key, | 155 | .key = key, |
| 159 | }; | 156 | }); |
| 160 | |||
| 161 | std::unique_lock lock(queue_mutex); | ||
| 162 | pending_queue.push(std::move(params)); | ||
| 163 | cv.notify_one(); | 157 | cv.notify_one(); |
| 164 | } | 158 | } |
| 165 | 159 | ||
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 618d309d2..1ed4212ee 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -212,10 +212,10 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 212 | return 0; | 212 | return 0; |
| 213 | case TextureFormat::R8G24: | 213 | case TextureFormat::R8G24: |
| 214 | if (component == 0) { | 214 | if (component == 0) { |
| 215 | return 8; | 215 | return 24; |
| 216 | } | 216 | } |
| 217 | if (component == 1) { | 217 | if (component == 1) { |
| 218 | return 24; | 218 | return 8; |
| 219 | } | 219 | } |
| 220 | return 0; | 220 | return 0; |
| 221 | case TextureFormat::R8G8: | 221 | case TextureFormat::R8G8: |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 8abb74d56..b16b54032 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -68,12 +68,12 @@ add_executable(yuzu | |||
| 68 | configuration/configure_input_advanced.cpp | 68 | configuration/configure_input_advanced.cpp |
| 69 | configuration/configure_input_advanced.h | 69 | configuration/configure_input_advanced.h |
| 70 | configuration/configure_input_advanced.ui | 70 | configuration/configure_input_advanced.ui |
| 71 | configuration/configure_input_dialog.cpp | ||
| 72 | configuration/configure_input_dialog.h | ||
| 73 | configuration/configure_input_dialog.ui | ||
| 74 | configuration/configure_input_player.cpp | 71 | configuration/configure_input_player.cpp |
| 75 | configuration/configure_input_player.h | 72 | configuration/configure_input_player.h |
| 76 | configuration/configure_input_player.ui | 73 | configuration/configure_input_player.ui |
| 74 | configuration/configure_input_profile_dialog.cpp | ||
| 75 | configuration/configure_input_profile_dialog.h | ||
| 76 | configuration/configure_input_profile_dialog.ui | ||
| 77 | configuration/configure_motion_touch.cpp | 77 | configuration/configure_motion_touch.cpp |
| 78 | configuration/configure_motion_touch.h | 78 | configuration/configure_motion_touch.h |
| 79 | configuration/configure_motion_touch.ui | 79 | configuration/configure_motion_touch.ui |
| @@ -105,9 +105,14 @@ add_executable(yuzu | |||
| 105 | configuration/configure_ui.cpp | 105 | configuration/configure_ui.cpp |
| 106 | configuration/configure_ui.h | 106 | configuration/configure_ui.h |
| 107 | configuration/configure_ui.ui | 107 | configuration/configure_ui.ui |
| 108 | configuration/configure_vibration.cpp | ||
| 109 | configuration/configure_vibration.h | ||
| 110 | configuration/configure_vibration.ui | ||
| 108 | configuration/configure_web.cpp | 111 | configuration/configure_web.cpp |
| 109 | configuration/configure_web.h | 112 | configuration/configure_web.h |
| 110 | configuration/configure_web.ui | 113 | configuration/configure_web.ui |
| 114 | configuration/input_profiles.cpp | ||
| 115 | configuration/input_profiles.h | ||
| 111 | debugger/console.cpp | 116 | debugger/console.cpp |
| 112 | debugger/console.h | 117 | debugger/console.h |
| 113 | debugger/profiler.cpp | 118 | debugger/profiler.cpp |
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index f122ba39d..1b320630c 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui | |||
| @@ -160,32 +160,12 @@ p, li { white-space: pre-wrap; } | |||
| 160 | <signal>accepted()</signal> | 160 | <signal>accepted()</signal> |
| 161 | <receiver>AboutDialog</receiver> | 161 | <receiver>AboutDialog</receiver> |
| 162 | <slot>accept()</slot> | 162 | <slot>accept()</slot> |
| 163 | <hints> | ||
| 164 | <hint type="sourcelabel"> | ||
| 165 | <x>248</x> | ||
| 166 | <y>254</y> | ||
| 167 | </hint> | ||
| 168 | <hint type="destinationlabel"> | ||
| 169 | <x>157</x> | ||
| 170 | <y>274</y> | ||
| 171 | </hint> | ||
| 172 | </hints> | ||
| 173 | </connection> | 163 | </connection> |
| 174 | <connection> | 164 | <connection> |
| 175 | <sender>buttonBox</sender> | 165 | <sender>buttonBox</sender> |
| 176 | <signal>rejected()</signal> | 166 | <signal>rejected()</signal> |
| 177 | <receiver>AboutDialog</receiver> | 167 | <receiver>AboutDialog</receiver> |
| 178 | <slot>reject()</slot> | 168 | <slot>reject()</slot> |
| 179 | <hints> | ||
| 180 | <hint type="sourcelabel"> | ||
| 181 | <x>316</x> | ||
| 182 | <y>260</y> | ||
| 183 | </hint> | ||
| 184 | <hint type="destinationlabel"> | ||
| 185 | <x>286</x> | ||
| 186 | <y>274</y> | ||
| 187 | </hint> | ||
| 188 | </hints> | ||
| 189 | </connection> | 169 | </connection> |
| 190 | </connections> | 170 | </connections> |
| 191 | </ui> | 171 | </ui> |
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index c6fa3e4f6..8ecfec770 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <thread> | ||
| 6 | 7 | ||
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 8 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| @@ -13,11 +14,16 @@ | |||
| 13 | #include "core/hle/service/sm/sm.h" | 14 | #include "core/hle/service/sm/sm.h" |
| 14 | #include "ui_controller.h" | 15 | #include "ui_controller.h" |
| 15 | #include "yuzu/applets/controller.h" | 16 | #include "yuzu/applets/controller.h" |
| 16 | #include "yuzu/configuration/configure_input_dialog.h" | 17 | #include "yuzu/configuration/configure_input.h" |
| 18 | #include "yuzu/configuration/configure_input_profile_dialog.h" | ||
| 19 | #include "yuzu/configuration/configure_vibration.h" | ||
| 20 | #include "yuzu/configuration/input_profiles.h" | ||
| 17 | #include "yuzu/main.h" | 21 | #include "yuzu/main.h" |
| 18 | 22 | ||
| 19 | namespace { | 23 | namespace { |
| 20 | 24 | ||
| 25 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 26 | |||
| 21 | constexpr std::array<std::array<bool, 4>, 8> led_patterns{{ | 27 | constexpr std::array<std::array<bool, 4>, 8> led_patterns{{ |
| 22 | {true, false, false, false}, | 28 | {true, false, false, false}, |
| 23 | {true, true, false, false}, | 29 | {true, true, false, false}, |
| @@ -106,7 +112,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 106 | QWidget* parent, Core::Frontend::ControllerParameters parameters_, | 112 | QWidget* parent, Core::Frontend::ControllerParameters parameters_, |
| 107 | InputCommon::InputSubsystem* input_subsystem_) | 113 | InputCommon::InputSubsystem* input_subsystem_) |
| 108 | : QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()), | 114 | : QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()), |
| 109 | parameters(std::move(parameters_)), input_subsystem(input_subsystem_) { | 115 | parameters(std::move(parameters_)), input_subsystem{input_subsystem_}, |
| 116 | input_profiles(std::make_unique<InputProfiles>()) { | ||
| 110 | ui->setupUi(this); | 117 | ui->setupUi(this); |
| 111 | 118 | ||
| 112 | player_widgets = { | 119 | player_widgets = { |
| @@ -223,12 +230,22 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 223 | } | 230 | } |
| 224 | } | 231 | } |
| 225 | 232 | ||
| 233 | connect(ui->vibrationButton, &QPushButton::clicked, this, | ||
| 234 | &QtControllerSelectorDialog::CallConfigureVibrationDialog); | ||
| 235 | |||
| 226 | connect(ui->inputConfigButton, &QPushButton::clicked, this, | 236 | connect(ui->inputConfigButton, &QPushButton::clicked, this, |
| 227 | &QtControllerSelectorDialog::CallConfigureInputDialog); | 237 | &QtControllerSelectorDialog::CallConfigureInputProfileDialog); |
| 228 | 238 | ||
| 229 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, | 239 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, |
| 230 | &QtControllerSelectorDialog::ApplyConfiguration); | 240 | &QtControllerSelectorDialog::ApplyConfiguration); |
| 231 | 241 | ||
| 242 | // Enhancement: Check if the parameters have already been met before disconnecting controllers. | ||
| 243 | // If all the parameters are met AND only allows a single player, | ||
| 244 | // stop the constructor here as we do not need to continue. | ||
| 245 | if (CheckIfParametersMet() && parameters.enable_single_mode) { | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 232 | // If keep_controllers_connected is false, forcefully disconnect all controllers | 249 | // If keep_controllers_connected is false, forcefully disconnect all controllers |
| 233 | if (!parameters.keep_controllers_connected) { | 250 | if (!parameters.keep_controllers_connected) { |
| 234 | for (auto player : player_groupboxes) { | 251 | for (auto player : player_groupboxes) { |
| @@ -236,58 +253,66 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 236 | } | 253 | } |
| 237 | } | 254 | } |
| 238 | 255 | ||
| 239 | CheckIfParametersMet(); | ||
| 240 | |||
| 241 | resize(0, 0); | 256 | resize(0, 0); |
| 242 | } | 257 | } |
| 243 | 258 | ||
| 244 | QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; | 259 | QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; |
| 245 | 260 | ||
| 246 | void QtControllerSelectorDialog::ApplyConfiguration() { | 261 | int QtControllerSelectorDialog::exec() { |
| 247 | // Update the controller state once more, just to be sure they are properly applied. | 262 | if (parameters_met && parameters.enable_single_mode) { |
| 248 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { | 263 | return QDialog::Accepted; |
| 249 | UpdateControllerState(index); | ||
| 250 | } | 264 | } |
| 265 | return QDialog::exec(); | ||
| 266 | } | ||
| 251 | 267 | ||
| 252 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 268 | void QtControllerSelectorDialog::ApplyConfiguration() { |
| 253 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); | 269 | const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); |
| 254 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 270 | Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()); |
| 271 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue()); | ||
| 255 | 272 | ||
| 256 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); | 273 | Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); |
| 274 | Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); | ||
| 257 | } | 275 | } |
| 258 | 276 | ||
| 259 | void QtControllerSelectorDialog::LoadConfiguration() { | 277 | void QtControllerSelectorDialog::LoadConfiguration() { |
| 260 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { | 278 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { |
| 261 | const auto connected = Settings::values.players[index].connected || | 279 | const auto connected = |
| 262 | (index == 0 && Settings::values.players[8].connected); | 280 | Settings::values.players.GetValue()[index].connected || |
| 281 | (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected); | ||
| 263 | player_groupboxes[index]->setChecked(connected); | 282 | player_groupboxes[index]->setChecked(connected); |
| 264 | connected_controller_checkboxes[index]->setChecked(connected); | 283 | connected_controller_checkboxes[index]->setChecked(connected); |
| 265 | emulated_controllers[index]->setCurrentIndex( | 284 | emulated_controllers[index]->setCurrentIndex( |
| 266 | GetIndexFromControllerType(Settings::values.players[index].controller_type)); | 285 | GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type)); |
| 267 | } | 286 | } |
| 268 | 287 | ||
| 269 | UpdateDockedState(Settings::values.players[8].connected); | 288 | UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected); |
| 270 | 289 | ||
| 271 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); | 290 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); |
| 291 | ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); | ||
| 272 | } | 292 | } |
| 273 | 293 | ||
| 274 | void QtControllerSelectorDialog::CallConfigureInputDialog() { | 294 | void QtControllerSelectorDialog::CallConfigureVibrationDialog() { |
| 275 | const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; | 295 | ConfigureVibration dialog(this); |
| 276 | |||
| 277 | ConfigureInputDialog dialog(this, max_supported_players, input_subsystem); | ||
| 278 | 296 | ||
| 279 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | 297 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | |
| 280 | Qt::WindowSystemMenuHint); | 298 | Qt::WindowSystemMenuHint); |
| 281 | dialog.setWindowModality(Qt::WindowModal); | 299 | dialog.setWindowModality(Qt::WindowModal); |
| 282 | dialog.exec(); | ||
| 283 | 300 | ||
| 284 | dialog.ApplyConfiguration(); | 301 | if (dialog.exec() == QDialog::Accepted) { |
| 302 | dialog.ApplyConfiguration(); | ||
| 303 | } | ||
| 304 | } | ||
| 285 | 305 | ||
| 286 | LoadConfiguration(); | 306 | void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { |
| 287 | CheckIfParametersMet(); | 307 | ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get()); |
| 308 | |||
| 309 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | ||
| 310 | Qt::WindowSystemMenuHint); | ||
| 311 | dialog.setWindowModality(Qt::WindowModal); | ||
| 312 | dialog.exec(); | ||
| 288 | } | 313 | } |
| 289 | 314 | ||
| 290 | void QtControllerSelectorDialog::CheckIfParametersMet() { | 315 | bool QtControllerSelectorDialog::CheckIfParametersMet() { |
| 291 | // Here, we check and validate the current configuration against all applicable parameters. | 316 | // Here, we check and validate the current configuration against all applicable parameters. |
| 292 | const auto num_connected_players = static_cast<int>( | 317 | const auto num_connected_players = static_cast<int>( |
| 293 | std::count_if(player_groupboxes.begin(), player_groupboxes.end(), | 318 | std::count_if(player_groupboxes.begin(), player_groupboxes.end(), |
| @@ -301,7 +326,7 @@ void QtControllerSelectorDialog::CheckIfParametersMet() { | |||
| 301 | num_connected_players > max_supported_players) { | 326 | num_connected_players > max_supported_players) { |
| 302 | parameters_met = false; | 327 | parameters_met = false; |
| 303 | ui->buttonBox->setEnabled(parameters_met); | 328 | ui->buttonBox->setEnabled(parameters_met); |
| 304 | return; | 329 | return parameters_met; |
| 305 | } | 330 | } |
| 306 | 331 | ||
| 307 | // Next, check against all connected controllers. | 332 | // Next, check against all connected controllers. |
| @@ -326,18 +351,13 @@ void QtControllerSelectorDialog::CheckIfParametersMet() { | |||
| 326 | return true; | 351 | return true; |
| 327 | }(); | 352 | }(); |
| 328 | 353 | ||
| 329 | if (!all_controllers_compatible) { | 354 | parameters_met = all_controllers_compatible; |
| 330 | parameters_met = false; | ||
| 331 | ui->buttonBox->setEnabled(parameters_met); | ||
| 332 | return; | ||
| 333 | } | ||
| 334 | |||
| 335 | parameters_met = true; | ||
| 336 | ui->buttonBox->setEnabled(parameters_met); | 355 | ui->buttonBox->setEnabled(parameters_met); |
| 356 | return parameters_met; | ||
| 337 | } | 357 | } |
| 338 | 358 | ||
| 339 | void QtControllerSelectorDialog::SetSupportedControllers() { | 359 | void QtControllerSelectorDialog::SetSupportedControllers() { |
| 340 | const QString theme = [this] { | 360 | const QString theme = [] { |
| 341 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | 361 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { |
| 342 | return QStringLiteral("_dark"); | 362 | return QStringLiteral("_dark"); |
| 343 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | 363 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { |
| @@ -426,7 +446,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) | |||
| 426 | } | 446 | } |
| 427 | }(); | 447 | }(); |
| 428 | 448 | ||
| 429 | const QString theme = [this] { | 449 | const QString theme = [] { |
| 430 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | 450 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { |
| 431 | return QStringLiteral("_dark"); | 451 | return QStringLiteral("_dark"); |
| 432 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | 452 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { |
| @@ -441,32 +461,48 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) | |||
| 441 | } | 461 | } |
| 442 | 462 | ||
| 443 | void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { | 463 | void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { |
| 444 | auto& player = Settings::values.players[player_index]; | 464 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 445 | 465 | ||
| 446 | player.controller_type = | 466 | const auto controller_type = |
| 447 | GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); | 467 | GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); |
| 448 | player.connected = player_groupboxes[player_index]->isChecked(); | 468 | const auto player_connected = player_groupboxes[player_index]->isChecked() && |
| 469 | controller_type != Settings::ControllerType::Handheld; | ||
| 449 | 470 | ||
| 450 | // Player 2-8 | 471 | if (player.controller_type == controller_type && player.connected == player_connected) { |
| 451 | if (player_index != 0) { | 472 | // Set vibration devices in the event that the input device has changed. |
| 452 | UpdateController(player.controller_type, player_index, player.connected); | 473 | ConfigureVibration::SetVibrationDevices(player_index); |
| 453 | return; | 474 | return; |
| 454 | } | 475 | } |
| 455 | 476 | ||
| 456 | // Player 1 and Handheld | 477 | // Disconnect the controller first. |
| 457 | auto& handheld = Settings::values.players[8]; | 478 | UpdateController(controller_type, player_index, false); |
| 458 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. | 479 | |
| 459 | if (player.controller_type == Settings::ControllerType::Handheld) { | 480 | player.controller_type = controller_type; |
| 460 | handheld = player; | 481 | player.connected = player_connected; |
| 461 | handheld.connected = player_groupboxes[player_index]->isChecked(); | 482 | |
| 462 | player.connected = false; // Disconnect Player 1 | 483 | ConfigureVibration::SetVibrationDevices(player_index); |
| 463 | } else { | 484 | |
| 464 | player.connected = player_groupboxes[player_index]->isChecked(); | 485 | // Handheld |
| 465 | handheld.connected = false; // Disconnect Handheld | 486 | if (player_index == 0) { |
| 487 | auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 488 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 489 | handheld = player; | ||
| 490 | } | ||
| 491 | handheld.connected = player_groupboxes[player_index]->isChecked() && | ||
| 492 | controller_type == Settings::ControllerType::Handheld; | ||
| 493 | UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected); | ||
| 466 | } | 494 | } |
| 467 | 495 | ||
| 468 | UpdateController(player.controller_type, player_index, player.connected); | 496 | if (!player.connected) { |
| 469 | UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected); | 497 | return; |
| 498 | } | ||
| 499 | |||
| 500 | // This emulates a delay between disconnecting and reconnecting controllers as some games | ||
| 501 | // do not respond to a change in controller type if it was instantaneous. | ||
| 502 | using namespace std::chrono_literals; | ||
| 503 | std::this_thread::sleep_for(20ms); | ||
| 504 | |||
| 505 | UpdateController(controller_type, player_index, player_connected); | ||
| 470 | } | 506 | } |
| 471 | 507 | ||
| 472 | void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { | 508 | void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { |
| @@ -520,8 +556,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) { | |||
| 520 | ui->radioDocked->setEnabled(!is_handheld); | 556 | ui->radioDocked->setEnabled(!is_handheld); |
| 521 | ui->radioUndocked->setEnabled(!is_handheld); | 557 | ui->radioUndocked->setEnabled(!is_handheld); |
| 522 | 558 | ||
| 523 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); | 559 | ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 524 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); | 560 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue()); |
| 525 | 561 | ||
| 526 | // Also force into undocked mode if the controller type is handheld. | 562 | // Also force into undocked mode if the controller type is handheld. |
| 527 | if (is_handheld) { | 563 | if (is_handheld) { |
| @@ -564,8 +600,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { | |||
| 564 | 600 | ||
| 565 | for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { | 601 | for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { |
| 566 | // Disconnect any unsupported players here and disable or hide them if applicable. | 602 | // Disconnect any unsupported players here and disable or hide them if applicable. |
| 567 | Settings::values.players[index].connected = false; | 603 | Settings::values.players.GetValue()[index].connected = false; |
| 568 | UpdateController(Settings::values.players[index].controller_type, index, false); | 604 | UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false); |
| 569 | // Hide the player widgets when max_supported_controllers is less than or equal to 4. | 605 | // Hide the player widgets when max_supported_controllers is less than or equal to 4. |
| 570 | if (max_supported_players <= 4) { | 606 | if (max_supported_players <= 4) { |
| 571 | player_widgets[index]->hide(); | 607 | player_widgets[index]->hide(); |
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 729ecc831..4344e1dd0 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h | |||
| @@ -16,6 +16,8 @@ class QDialogButtonBox; | |||
| 16 | class QGroupBox; | 16 | class QGroupBox; |
| 17 | class QLabel; | 17 | class QLabel; |
| 18 | 18 | ||
| 19 | class InputProfiles; | ||
| 20 | |||
| 19 | namespace InputCommon { | 21 | namespace InputCommon { |
| 20 | class InputSubsystem; | 22 | class InputSubsystem; |
| 21 | } | 23 | } |
| @@ -33,6 +35,8 @@ public: | |||
| 33 | InputCommon::InputSubsystem* input_subsystem_); | 35 | InputCommon::InputSubsystem* input_subsystem_); |
| 34 | ~QtControllerSelectorDialog() override; | 36 | ~QtControllerSelectorDialog() override; |
| 35 | 37 | ||
| 38 | int exec() override; | ||
| 39 | |||
| 36 | private: | 40 | private: |
| 37 | // Applies the current configuration. | 41 | // Applies the current configuration. |
| 38 | void ApplyConfiguration(); | 42 | void ApplyConfiguration(); |
| @@ -40,12 +44,15 @@ private: | |||
| 40 | // Loads the current input configuration into the frontend applet. | 44 | // Loads the current input configuration into the frontend applet. |
| 41 | void LoadConfiguration(); | 45 | void LoadConfiguration(); |
| 42 | 46 | ||
| 43 | // Initializes the "Configure Input" Dialog. | 47 | // Initializes the "Configure Vibration" Dialog. |
| 44 | void CallConfigureInputDialog(); | 48 | void CallConfigureVibrationDialog(); |
| 45 | 49 | ||
| 46 | // Checks the current configuration against the given parameters and | 50 | // Initializes the "Create Input Profile" Dialog. |
| 47 | // sets the value of parameters_met. | 51 | void CallConfigureInputProfileDialog(); |
| 48 | void CheckIfParametersMet(); | 52 | |
| 53 | // Checks the current configuration against the given parameters. | ||
| 54 | // This sets and returns the value of parameters_met. | ||
| 55 | bool CheckIfParametersMet(); | ||
| 49 | 56 | ||
| 50 | // Sets the controller icons for "Supported Controller Types". | 57 | // Sets the controller icons for "Supported Controller Types". |
| 51 | void SetSupportedControllers(); | 58 | void SetSupportedControllers(); |
| @@ -78,6 +85,8 @@ private: | |||
| 78 | 85 | ||
| 79 | InputCommon::InputSubsystem* input_subsystem; | 86 | InputCommon::InputSubsystem* input_subsystem; |
| 80 | 87 | ||
| 88 | std::unique_ptr<InputProfiles> input_profiles; | ||
| 89 | |||
| 81 | // This is true if and only if all parameters are met. Otherwise, this is false. | 90 | // This is true if and only if all parameters are met. Otherwise, this is false. |
| 82 | // This determines whether the "OK" button can be clicked to exit the applet. | 91 | // This determines whether the "OK" button can be clicked to exit the applet. |
| 83 | bool parameters_met{false}; | 92 | bool parameters_met{false}; |
diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui index c4108a979..c8cb6bcf3 100644 --- a/src/yuzu/applets/controller.ui +++ b/src/yuzu/applets/controller.ui | |||
| @@ -1217,9 +1217,6 @@ | |||
| 1217 | </item> | 1217 | </item> |
| 1218 | <item> | 1218 | <item> |
| 1219 | <widget class="QComboBox" name="comboPlayer3Emulated"> | 1219 | <widget class="QComboBox" name="comboPlayer3Emulated"> |
| 1220 | <property name="editable"> | ||
| 1221 | <bool>false</bool> | ||
| 1222 | </property> | ||
| 1223 | <item> | 1220 | <item> |
| 1224 | <property name="text"> | 1221 | <property name="text"> |
| 1225 | <string>Pro Controller</string> | 1222 | <string>Pro Controller</string> |
| @@ -2279,7 +2276,7 @@ | |||
| 2279 | <number>6</number> | 2276 | <number>6</number> |
| 2280 | </property> | 2277 | </property> |
| 2281 | <property name="leftMargin"> | 2278 | <property name="leftMargin"> |
| 2282 | <number>6</number> | 2279 | <number>8</number> |
| 2283 | </property> | 2280 | </property> |
| 2284 | <property name="topMargin"> | 2281 | <property name="topMargin"> |
| 2285 | <number>6</number> | 2282 | <number>6</number> |
| @@ -2332,30 +2329,24 @@ | |||
| 2332 | <number>3</number> | 2329 | <number>3</number> |
| 2333 | </property> | 2330 | </property> |
| 2334 | <item> | 2331 | <item> |
| 2335 | <widget class="QSpinBox" name="vibrationSpin"> | 2332 | <widget class="QPushButton" name="vibrationButton"> |
| 2336 | <property name="minimumSize"> | 2333 | <property name="minimumSize"> |
| 2337 | <size> | 2334 | <size> |
| 2338 | <width>65</width> | 2335 | <width>68</width> |
| 2339 | <height>0</height> | 2336 | <height>0</height> |
| 2340 | </size> | 2337 | </size> |
| 2341 | </property> | 2338 | </property> |
| 2342 | <property name="maximumSize"> | 2339 | <property name="maximumSize"> |
| 2343 | <size> | 2340 | <size> |
| 2344 | <width>65</width> | 2341 | <width>68</width> |
| 2345 | <height>16777215</height> | 2342 | <height>16777215</height> |
| 2346 | </size> | 2343 | </size> |
| 2347 | </property> | 2344 | </property> |
| 2348 | <property name="suffix"> | 2345 | <property name="styleSheet"> |
| 2349 | <string>%</string> | 2346 | <string notr="true">min-width: 68px;</string> |
| 2350 | </property> | ||
| 2351 | <property name="minimum"> | ||
| 2352 | <number>1</number> | ||
| 2353 | </property> | ||
| 2354 | <property name="maximum"> | ||
| 2355 | <number>200</number> | ||
| 2356 | </property> | 2347 | </property> |
| 2357 | <property name="value"> | 2348 | <property name="text"> |
| 2358 | <number>100</number> | 2349 | <string>Configure</string> |
| 2359 | </property> | 2350 | </property> |
| 2360 | </widget> | 2351 | </widget> |
| 2361 | </item> | 2352 | </item> |
| @@ -2387,18 +2378,18 @@ | |||
| 2387 | <widget class="QPushButton" name="motionButton"> | 2378 | <widget class="QPushButton" name="motionButton"> |
| 2388 | <property name="minimumSize"> | 2379 | <property name="minimumSize"> |
| 2389 | <size> | 2380 | <size> |
| 2390 | <width>57</width> | 2381 | <width>68</width> |
| 2391 | <height>0</height> | 2382 | <height>0</height> |
| 2392 | </size> | 2383 | </size> |
| 2393 | </property> | 2384 | </property> |
| 2394 | <property name="maximumSize"> | 2385 | <property name="maximumSize"> |
| 2395 | <size> | 2386 | <size> |
| 2396 | <width>55</width> | 2387 | <width>68</width> |
| 2397 | <height>16777215</height> | 2388 | <height>16777215</height> |
| 2398 | </size> | 2389 | </size> |
| 2399 | </property> | 2390 | </property> |
| 2400 | <property name="styleSheet"> | 2391 | <property name="styleSheet"> |
| 2401 | <string notr="true">min-width: 55px;</string> | 2392 | <string notr="true">min-width: 68px;</string> |
| 2402 | </property> | 2393 | </property> |
| 2403 | <property name="text"> | 2394 | <property name="text"> |
| 2404 | <string>Configure</string> | 2395 | <string>Configure</string> |
| @@ -2411,7 +2402,7 @@ | |||
| 2411 | <item> | 2402 | <item> |
| 2412 | <widget class="QGroupBox" name="inputConfigGroup"> | 2403 | <widget class="QGroupBox" name="inputConfigGroup"> |
| 2413 | <property name="title"> | 2404 | <property name="title"> |
| 2414 | <string>Input Config</string> | 2405 | <string>Profiles</string> |
| 2415 | </property> | 2406 | </property> |
| 2416 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | 2407 | <layout class="QHBoxLayout" name="horizontalLayout_7"> |
| 2417 | <property name="leftMargin"> | 2408 | <property name="leftMargin"> |
| @@ -2430,15 +2421,15 @@ | |||
| 2430 | <widget class="QPushButton" name="inputConfigButton"> | 2421 | <widget class="QPushButton" name="inputConfigButton"> |
| 2431 | <property name="maximumSize"> | 2422 | <property name="maximumSize"> |
| 2432 | <size> | 2423 | <size> |
| 2433 | <width>65</width> | 2424 | <width>68</width> |
| 2434 | <height>16777215</height> | 2425 | <height>16777215</height> |
| 2435 | </size> | 2426 | </size> |
| 2436 | </property> | 2427 | </property> |
| 2437 | <property name="styleSheet"> | 2428 | <property name="styleSheet"> |
| 2438 | <string notr="true">min-width: 55px;</string> | 2429 | <string notr="true">min-width: 68px;</string> |
| 2439 | </property> | 2430 | </property> |
| 2440 | <property name="text"> | 2431 | <property name="text"> |
| 2441 | <string>Open</string> | 2432 | <string>Create</string> |
| 2442 | </property> | 2433 | </property> |
| 2443 | </widget> | 2434 | </widget> |
| 2444 | </item> | 2435 | </item> |
| @@ -2657,16 +2648,6 @@ | |||
| 2657 | <signal>accepted()</signal> | 2648 | <signal>accepted()</signal> |
| 2658 | <receiver>QtControllerSelectorDialog</receiver> | 2649 | <receiver>QtControllerSelectorDialog</receiver> |
| 2659 | <slot>accept()</slot> | 2650 | <slot>accept()</slot> |
| 2660 | <hints> | ||
| 2661 | <hint type="sourcelabel"> | ||
| 2662 | <x>20</x> | ||
| 2663 | <y>20</y> | ||
| 2664 | </hint> | ||
| 2665 | <hint type="destinationlabel"> | ||
| 2666 | <x>20</x> | ||
| 2667 | <y>20</y> | ||
| 2668 | </hint> | ||
| 2669 | </hints> | ||
| 2670 | </connection> | 2651 | </connection> |
| 2671 | </connections> | 2652 | </connections> |
| 2672 | </ui> | 2653 | </ui> |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 408eac2b7..f0338cf7a 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <QMessageBox> | 10 | #include <QMessageBox> |
| 11 | #include <QPainter> | 11 | #include <QPainter> |
| 12 | #include <QScreen> | 12 | #include <QScreen> |
| 13 | #include <QString> | ||
| 13 | #include <QStringList> | 14 | #include <QStringList> |
| 14 | #include <QWindow> | 15 | #include <QWindow> |
| 15 | 16 | ||
| @@ -301,6 +302,12 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, | |||
| 301 | this->setMouseTracking(true); | 302 | this->setMouseTracking(true); |
| 302 | 303 | ||
| 303 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); | 304 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); |
| 305 | connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, | ||
| 306 | Qt::QueuedConnection); | ||
| 307 | } | ||
| 308 | |||
| 309 | void GRenderWindow::ExecuteProgram(std::size_t program_index) { | ||
| 310 | emit ExecuteProgramSignal(program_index); | ||
| 304 | } | 311 | } |
| 305 | 312 | ||
| 306 | GRenderWindow::~GRenderWindow() { | 313 | GRenderWindow::~GRenderWindow() { |
| @@ -381,7 +388,12 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { | |||
| 381 | } | 388 | } |
| 382 | 389 | ||
| 383 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { | 390 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { |
| 384 | // touch input is handled in TouchBeginEvent | 391 | if (!Settings::values.touchscreen.enabled) { |
| 392 | input_subsystem->GetKeyboard()->PressKey(event->button()); | ||
| 393 | return; | ||
| 394 | } | ||
| 395 | |||
| 396 | // Touch input is handled in TouchBeginEvent | ||
| 385 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 397 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 386 | return; | 398 | return; |
| 387 | } | 399 | } |
| @@ -397,7 +409,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 397 | } | 409 | } |
| 398 | 410 | ||
| 399 | void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | 411 | void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { |
| 400 | // touch input is handled in TouchUpdateEvent | 412 | // Touch input is handled in TouchUpdateEvent |
| 401 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 413 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 402 | return; | 414 | return; |
| 403 | } | 415 | } |
| @@ -410,7 +422,12 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 410 | } | 422 | } |
| 411 | 423 | ||
| 412 | void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | 424 | void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { |
| 413 | // touch input is handled in TouchEndEvent | 425 | if (!Settings::values.touchscreen.enabled) { |
| 426 | input_subsystem->GetKeyboard()->ReleaseKey(event->button()); | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | // Touch input is handled in TouchEndEvent | ||
| 414 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 431 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 415 | return; | 432 | return; |
| 416 | } | 433 | } |
| @@ -603,19 +620,33 @@ bool GRenderWindow::LoadOpenGL() { | |||
| 603 | auto context = CreateSharedContext(); | 620 | auto context = CreateSharedContext(); |
| 604 | auto scope = context->Acquire(); | 621 | auto scope = context->Acquire(); |
| 605 | if (!gladLoadGL()) { | 622 | if (!gladLoadGL()) { |
| 606 | QMessageBox::critical(this, tr("Error while initializing OpenGL 4.3!"), | 623 | QMessageBox::warning( |
| 607 | tr("Your GPU may not support OpenGL 4.3, or you do not have the " | 624 | this, tr("Error while initializing OpenGL!"), |
| 608 | "latest graphics driver.")); | 625 | tr("Your GPU may not support OpenGL, or you do not have the latest graphics driver.")); |
| 626 | return false; | ||
| 627 | } | ||
| 628 | |||
| 629 | const QString renderer = | ||
| 630 | QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER))); | ||
| 631 | |||
| 632 | if (!GLAD_GL_VERSION_4_3) { | ||
| 633 | LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString()); | ||
| 634 | QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"), | ||
| 635 | tr("Your GPU may not support OpenGL 4.3, or you do not have the " | ||
| 636 | "latest graphics driver.<br><br>GL Renderer:<br>%1") | ||
| 637 | .arg(renderer)); | ||
| 609 | return false; | 638 | return false; |
| 610 | } | 639 | } |
| 611 | 640 | ||
| 612 | QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions(); | 641 | QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions(); |
| 613 | if (!unsupported_gl_extensions.empty()) { | 642 | if (!unsupported_gl_extensions.empty()) { |
| 614 | QMessageBox::critical( | 643 | QMessageBox::warning( |
| 615 | this, tr("Error while initializing OpenGL!"), | 644 | this, tr("Error while initializing OpenGL!"), |
| 616 | tr("Your GPU may not support one or more required OpenGL extensions. Please ensure you " | 645 | tr("Your GPU may not support one or more required OpenGL extensions. Please ensure you " |
| 617 | "have the latest graphics driver.<br><br>Unsupported extensions:<br>") + | 646 | "have the latest graphics driver.<br><br>GL Renderer:<br>%1<br><br>Unsupported " |
| 618 | unsupported_gl_extensions.join(QStringLiteral("<br>"))); | 647 | "extensions:<br>%2") |
| 648 | .arg(renderer) | ||
| 649 | .arg(unsupported_gl_extensions.join(QStringLiteral("<br>")))); | ||
| 619 | return false; | 650 | return false; |
| 620 | } | 651 | } |
| 621 | return true; | 652 | return true; |
| @@ -645,8 +676,13 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const { | |||
| 645 | if (!GLAD_GL_ARB_depth_buffer_float) | 676 | if (!GLAD_GL_ARB_depth_buffer_float) |
| 646 | unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float")); | 677 | unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float")); |
| 647 | 678 | ||
| 648 | for (const QString& ext : unsupported_ext) | 679 | if (!unsupported_ext.empty()) { |
| 649 | LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString()); | 680 | LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", |
| 681 | glGetString(GL_RENDERER)); | ||
| 682 | } | ||
| 683 | for (const QString& ext : unsupported_ext) { | ||
| 684 | LOG_ERROR(Frontend, "Unsupported GL extension: {}", ext.toStdString()); | ||
| 685 | } | ||
| 650 | 686 | ||
| 651 | return unsupported_ext; | 687 | return unsupported_ext; |
| 652 | } | 688 | } |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index ca35cf831..503b4f89e 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -166,6 +166,12 @@ public: | |||
| 166 | 166 | ||
| 167 | std::pair<u32, u32> ScaleTouch(const QPointF& pos) const; | 167 | std::pair<u32, u32> ScaleTouch(const QPointF& pos) const; |
| 168 | 168 | ||
| 169 | /** | ||
| 170 | * Instructs the window to re-launch the application using the specified program_index. | ||
| 171 | * @param program_index Specifies the index within the application of the program to launch. | ||
| 172 | */ | ||
| 173 | void ExecuteProgram(std::size_t program_index); | ||
| 174 | |||
| 169 | public slots: | 175 | public slots: |
| 170 | void OnEmulationStarting(EmuThread* emu_thread); | 176 | void OnEmulationStarting(EmuThread* emu_thread); |
| 171 | void OnEmulationStopping(); | 177 | void OnEmulationStopping(); |
| @@ -175,6 +181,7 @@ signals: | |||
| 175 | /// Emitted when the window is closed | 181 | /// Emitted when the window is closed |
| 176 | void Closed(); | 182 | void Closed(); |
| 177 | void FirstFrameDisplayed(); | 183 | void FirstFrameDisplayed(); |
| 184 | void ExecuteProgramSignal(std::size_t program_index); | ||
| 178 | 185 | ||
| 179 | private: | 186 | private: |
| 180 | void TouchBeginEvent(const QTouchEvent* event); | 187 | void TouchBeginEvent(const QTouchEvent* event); |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 1ce62e4a6..3c423a271 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <QKeySequence> | 6 | #include <QKeySequence> |
| 7 | #include <QSettings> | 7 | #include <QSettings> |
| 8 | #include "common/common_paths.h" | ||
| 8 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 9 | #include "core/hle/service/acc/profile_manager.h" | 10 | #include "core/hle/service/acc/profile_manager.h" |
| 10 | #include "core/hle/service/hid/controllers/npad.h" | 11 | #include "core/hle/service/hid/controllers/npad.h" |
| @@ -14,14 +15,10 @@ | |||
| 14 | 15 | ||
| 15 | namespace FS = Common::FS; | 16 | namespace FS = Common::FS; |
| 16 | 17 | ||
| 17 | Config::Config(const std::string& config_file, bool is_global) { | 18 | Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) { |
| 18 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 19 | global = config_type == ConfigType::GlobalConfig; |
| 19 | qt_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + config_file; | 20 | |
| 20 | FS::CreateFullPath(qt_config_loc); | 21 | Initialize(config_name); |
| 21 | qt_config = | ||
| 22 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||
| 23 | global = is_global; | ||
| 24 | Reload(); | ||
| 25 | } | 22 | } |
| 26 | 23 | ||
| 27 | Config::~Config() { | 24 | Config::~Config() { |
| @@ -242,84 +239,152 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ | |||
| 242 | }}; | 239 | }}; |
| 243 | // clang-format on | 240 | // clang-format on |
| 244 | 241 | ||
| 245 | void Config::ReadPlayerValues() { | 242 | void Config::Initialize(const std::string& config_name) { |
| 246 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 243 | switch (type) { |
| 247 | auto& player = Settings::values.players[p]; | 244 | case ConfigType::GlobalConfig: |
| 245 | qt_config_loc = fmt::format("{}" DIR_SEP "{}.ini", FS::GetUserPath(FS::UserPath::ConfigDir), | ||
| 246 | config_name); | ||
| 247 | FS::CreateFullPath(qt_config_loc); | ||
| 248 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 249 | QSettings::IniFormat); | ||
| 250 | Reload(); | ||
| 251 | break; | ||
| 252 | case ConfigType::PerGameConfig: | ||
| 253 | qt_config_loc = fmt::format("{}custom" DIR_SEP "{}.ini", | ||
| 254 | FS::GetUserPath(FS::UserPath::ConfigDir), config_name); | ||
| 255 | FS::CreateFullPath(qt_config_loc); | ||
| 256 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 257 | QSettings::IniFormat); | ||
| 258 | Reload(); | ||
| 259 | break; | ||
| 260 | case ConfigType::InputProfile: | ||
| 261 | qt_config_loc = fmt::format("{}input" DIR_SEP "{}.ini", | ||
| 262 | FS::GetUserPath(FS::UserPath::ConfigDir), config_name); | ||
| 263 | FS::CreateFullPath(qt_config_loc); | ||
| 264 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 265 | QSettings::IniFormat); | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | void Config::ReadPlayerValue(std::size_t player_index) { | ||
| 271 | const QString player_prefix = [this, player_index] { | ||
| 272 | if (type == ConfigType::InputProfile) { | ||
| 273 | return QString{}; | ||
| 274 | } else { | ||
| 275 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 276 | } | ||
| 277 | }(); | ||
| 278 | |||
| 279 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 280 | |||
| 281 | if (player_prefix.isEmpty()) { | ||
| 282 | const auto controller = static_cast<Settings::ControllerType>( | ||
| 283 | qt_config | ||
| 284 | ->value(QStringLiteral("%1type").arg(player_prefix), | ||
| 285 | static_cast<u8>(Settings::ControllerType::ProController)) | ||
| 286 | .toUInt()); | ||
| 248 | 287 | ||
| 288 | if (controller == Settings::ControllerType::LeftJoycon || | ||
| 289 | controller == Settings::ControllerType::RightJoycon) { | ||
| 290 | player.controller_type = controller; | ||
| 291 | } | ||
| 292 | } else { | ||
| 249 | player.connected = | 293 | player.connected = |
| 250 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); | 294 | ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0) |
| 295 | .toBool(); | ||
| 251 | 296 | ||
| 252 | player.controller_type = static_cast<Settings::ControllerType>( | 297 | player.controller_type = static_cast<Settings::ControllerType>( |
| 253 | qt_config | 298 | qt_config |
| 254 | ->value(QStringLiteral("player_%1_type").arg(p), | 299 | ->value(QStringLiteral("%1type").arg(player_prefix), |
| 255 | static_cast<u8>(Settings::ControllerType::ProController)) | 300 | static_cast<u8>(Settings::ControllerType::ProController)) |
| 256 | .toUInt()); | 301 | .toUInt()); |
| 257 | 302 | ||
| 303 | player.vibration_enabled = | ||
| 304 | qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true) | ||
| 305 | .toBool(); | ||
| 306 | |||
| 307 | player.vibration_strength = | ||
| 308 | qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100) | ||
| 309 | .toInt(); | ||
| 310 | |||
| 258 | player.body_color_left = qt_config | 311 | player.body_color_left = qt_config |
| 259 | ->value(QStringLiteral("player_%1_body_color_left").arg(p), | 312 | ->value(QStringLiteral("%1body_color_left").arg(player_prefix), |
| 260 | Settings::JOYCON_BODY_NEON_BLUE) | 313 | Settings::JOYCON_BODY_NEON_BLUE) |
| 261 | .toUInt(); | 314 | .toUInt(); |
| 262 | player.body_color_right = qt_config | 315 | player.body_color_right = |
| 263 | ->value(QStringLiteral("player_%1_body_color_right").arg(p), | 316 | qt_config |
| 264 | Settings::JOYCON_BODY_NEON_RED) | 317 | ->value(QStringLiteral("%1body_color_right").arg(player_prefix), |
| 265 | .toUInt(); | 318 | Settings::JOYCON_BODY_NEON_RED) |
| 266 | player.button_color_left = qt_config | 319 | .toUInt(); |
| 267 | ->value(QStringLiteral("player_%1_button_color_left").arg(p), | 320 | player.button_color_left = |
| 268 | Settings::JOYCON_BUTTONS_NEON_BLUE) | 321 | qt_config |
| 269 | .toUInt(); | 322 | ->value(QStringLiteral("%1button_color_left").arg(player_prefix), |
| 323 | Settings::JOYCON_BUTTONS_NEON_BLUE) | ||
| 324 | .toUInt(); | ||
| 270 | player.button_color_right = | 325 | player.button_color_right = |
| 271 | qt_config | 326 | qt_config |
| 272 | ->value(QStringLiteral("player_%1_button_color_right").arg(p), | 327 | ->value(QStringLiteral("%1button_color_right").arg(player_prefix), |
| 273 | Settings::JOYCON_BUTTONS_NEON_RED) | 328 | Settings::JOYCON_BUTTONS_NEON_RED) |
| 274 | .toUInt(); | 329 | .toUInt(); |
| 330 | } | ||
| 275 | 331 | ||
| 276 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 332 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 277 | const std::string default_param = | 333 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 278 | InputCommon::GenerateKeyboardParam(default_buttons[i]); | 334 | auto& player_buttons = player.buttons[i]; |
| 279 | auto& player_buttons = player.buttons[i]; | 335 | |
| 280 | 336 | player_buttons = qt_config | |
| 281 | player_buttons = qt_config | 337 | ->value(QStringLiteral("%1").arg(player_prefix) + |
| 282 | ->value(QStringLiteral("player_%1_").arg(p) + | 338 | QString::fromUtf8(Settings::NativeButton::mapping[i]), |
| 283 | QString::fromUtf8(Settings::NativeButton::mapping[i]), | 339 | QString::fromStdString(default_param)) |
| 284 | QString::fromStdString(default_param)) | 340 | .toString() |
| 285 | .toString() | 341 | .toStdString(); |
| 286 | .toStdString(); | 342 | if (player_buttons.empty()) { |
| 287 | if (player_buttons.empty()) { | 343 | player_buttons = default_param; |
| 288 | player_buttons = default_param; | ||
| 289 | } | ||
| 290 | } | 344 | } |
| 345 | } | ||
| 291 | 346 | ||
| 292 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | 347 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 293 | const std::string default_param = | 348 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 294 | InputCommon::GenerateKeyboardParam(default_motions[i]); | 349 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 295 | auto& player_motions = player.motions[i]; | 350 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 296 | 351 | auto& player_analogs = player.analogs[i]; | |
| 297 | player_motions = qt_config | 352 | |
| 298 | ->value(QStringLiteral("player_%1_").arg(p) + | 353 | player_analogs = qt_config |
| 299 | QString::fromUtf8(Settings::NativeMotion::mapping[i]), | 354 | ->value(QStringLiteral("%1").arg(player_prefix) + |
| 300 | QString::fromStdString(default_param)) | 355 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), |
| 301 | .toString() | 356 | QString::fromStdString(default_param)) |
| 302 | .toStdString(); | 357 | .toString() |
| 303 | if (player_motions.empty()) { | 358 | .toStdString(); |
| 304 | player_motions = default_param; | 359 | if (player_analogs.empty()) { |
| 305 | } | 360 | player_analogs = default_param; |
| 306 | } | 361 | } |
| 362 | } | ||
| 307 | 363 | ||
| 308 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 364 | for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { |
| 309 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 365 | auto& player_vibrations = player.vibrations[i]; |
| 310 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 366 | |
| 311 | default_analogs[i][3], default_stick_mod[i], 0.5f); | 367 | player_vibrations = |
| 312 | auto& player_analogs = player.analogs[i]; | 368 | qt_config |
| 313 | 369 | ->value(QStringLiteral("%1").arg(player_prefix) + | |
| 314 | player_analogs = qt_config | 370 | QString::fromUtf8(Settings::NativeVibration::mapping[i]), |
| 315 | ->value(QStringLiteral("player_%1_").arg(p) + | 371 | QString{}) |
| 316 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), | 372 | .toString() |
| 317 | QString::fromStdString(default_param)) | 373 | .toStdString(); |
| 318 | .toString() | 374 | } |
| 319 | .toStdString(); | 375 | |
| 320 | if (player_analogs.empty()) { | 376 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { |
| 321 | player_analogs = default_param; | 377 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); |
| 322 | } | 378 | auto& player_motions = player.motions[i]; |
| 379 | |||
| 380 | player_motions = qt_config | ||
| 381 | ->value(QStringLiteral("%1").arg(player_prefix) + | ||
| 382 | QString::fromUtf8(Settings::NativeMotion::mapping[i]), | ||
| 383 | QString::fromStdString(default_param)) | ||
| 384 | .toString() | ||
| 385 | .toStdString(); | ||
| 386 | if (player_motions.empty()) { | ||
| 387 | player_motions = default_param; | ||
| 323 | } | 388 | } |
| 324 | } | 389 | } |
| 325 | } | 390 | } |
| @@ -436,18 +501,21 @@ void Config::ReadAudioValues() { | |||
| 436 | void Config::ReadControlValues() { | 501 | void Config::ReadControlValues() { |
| 437 | qt_config->beginGroup(QStringLiteral("Controls")); | 502 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 438 | 503 | ||
| 439 | ReadPlayerValues(); | 504 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 505 | ReadPlayerValue(p); | ||
| 506 | } | ||
| 440 | ReadDebugValues(); | 507 | ReadDebugValues(); |
| 441 | ReadKeyboardValues(); | 508 | ReadKeyboardValues(); |
| 442 | ReadMouseValues(); | 509 | ReadMouseValues(); |
| 443 | ReadTouchscreenValues(); | 510 | ReadTouchscreenValues(); |
| 444 | ReadMotionTouchValues(); | 511 | ReadMotionTouchValues(); |
| 445 | 512 | ||
| 446 | Settings::values.vibration_enabled = | 513 | ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false); |
| 447 | ReadSetting(QStringLiteral("vibration_enabled"), true).toBool(); | 514 | ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), |
| 448 | Settings::values.motion_enabled = ReadSetting(QStringLiteral("motion_enabled"), true).toBool(); | 515 | true); |
| 449 | Settings::values.use_docked_mode = | 516 | ReadSettingGlobal(Settings::values.enable_accurate_vibrations, |
| 450 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | 517 | QStringLiteral("enable_accurate_vibrations"), false); |
| 518 | ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true); | ||
| 451 | 519 | ||
| 452 | qt_config->endGroup(); | 520 | qt_config->endGroup(); |
| 453 | } | 521 | } |
| @@ -581,6 +649,8 @@ void Config::ReadDebuggingValues() { | |||
| 581 | Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), false).toBool(); | 649 | Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), false).toBool(); |
| 582 | Settings::values.disable_macro_jit = | 650 | Settings::values.disable_macro_jit = |
| 583 | ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); | 651 | ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); |
| 652 | Settings::values.extended_logging = | ||
| 653 | ReadSetting(QStringLiteral("extended_logging"), false).toBool(); | ||
| 584 | 654 | ||
| 585 | qt_config->endGroup(); | 655 | qt_config->endGroup(); |
| 586 | } | 656 | } |
| @@ -920,49 +990,64 @@ void Config::ReadValues() { | |||
| 920 | ReadSystemValues(); | 990 | ReadSystemValues(); |
| 921 | } | 991 | } |
| 922 | 992 | ||
| 923 | void Config::SavePlayerValues() { | 993 | void Config::SavePlayerValue(std::size_t player_index) { |
| 924 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 994 | const QString player_prefix = [this, player_index] { |
| 925 | const auto& player = Settings::values.players[p]; | 995 | if (type == ConfigType::InputProfile) { |
| 996 | return QString{}; | ||
| 997 | } else { | ||
| 998 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 999 | } | ||
| 1000 | }(); | ||
| 926 | 1001 | ||
| 927 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); | 1002 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 928 | WriteSetting(QStringLiteral("player_%1_type").arg(p), | ||
| 929 | static_cast<u8>(player.controller_type), | ||
| 930 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 931 | 1003 | ||
| 932 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, | 1004 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), |
| 1005 | static_cast<u8>(player.controller_type), | ||
| 1006 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 1007 | |||
| 1008 | if (!player_prefix.isEmpty()) { | ||
| 1009 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false); | ||
| 1010 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | ||
| 1011 | player.vibration_enabled, true); | ||
| 1012 | WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), | ||
| 1013 | player.vibration_strength, 100); | ||
| 1014 | WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left, | ||
| 933 | Settings::JOYCON_BODY_NEON_BLUE); | 1015 | Settings::JOYCON_BODY_NEON_BLUE); |
| 934 | WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right, | 1016 | WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix), |
| 935 | Settings::JOYCON_BODY_NEON_RED); | 1017 | player.body_color_right, Settings::JOYCON_BODY_NEON_RED); |
| 936 | WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left, | 1018 | WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix), |
| 937 | Settings::JOYCON_BUTTONS_NEON_BLUE); | 1019 | player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE); |
| 938 | WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p), | 1020 | WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix), |
| 939 | player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); | 1021 | player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); |
| 1022 | } | ||
| 940 | 1023 | ||
| 941 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 1024 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 942 | const std::string default_param = | 1025 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 943 | InputCommon::GenerateKeyboardParam(default_buttons[i]); | 1026 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 944 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1027 | QString::fromStdString(Settings::NativeButton::mapping[i]), |
| 945 | QString::fromStdString(Settings::NativeButton::mapping[i]), | 1028 | QString::fromStdString(player.buttons[i]), |
| 946 | QString::fromStdString(player.buttons[i]), | 1029 | QString::fromStdString(default_param)); |
| 947 | QString::fromStdString(default_param)); | 1030 | } |
| 948 | } | 1031 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 949 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | 1032 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 950 | const std::string default_param = | 1033 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 951 | InputCommon::GenerateKeyboardParam(default_motions[i]); | 1034 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 952 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1035 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 953 | QString::fromStdString(Settings::NativeMotion::mapping[i]), | 1036 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 954 | QString::fromStdString(player.motions[i]), | 1037 | QString::fromStdString(player.analogs[i]), |
| 955 | QString::fromStdString(default_param)); | 1038 | QString::fromStdString(default_param)); |
| 956 | } | 1039 | } |
| 957 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 1040 | for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { |
| 958 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 1041 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 959 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 1042 | QString::fromStdString(Settings::NativeVibration::mapping[i]), |
| 960 | default_analogs[i][3], default_stick_mod[i], 0.5f); | 1043 | QString::fromStdString(player.vibrations[i]), QString{}); |
| 961 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1044 | } |
| 962 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 1045 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { |
| 963 | QString::fromStdString(player.analogs[i]), | 1046 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); |
| 964 | QString::fromStdString(default_param)); | 1047 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 965 | } | 1048 | QString::fromStdString(Settings::NativeMotion::mapping[i]), |
| 1049 | QString::fromStdString(player.motions[i]), | ||
| 1050 | QString::fromStdString(default_param)); | ||
| 966 | } | 1051 | } |
| 967 | } | 1052 | } |
| 968 | 1053 | ||
| @@ -1087,14 +1172,20 @@ void Config::SaveAudioValues() { | |||
| 1087 | void Config::SaveControlValues() { | 1172 | void Config::SaveControlValues() { |
| 1088 | qt_config->beginGroup(QStringLiteral("Controls")); | 1173 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 1089 | 1174 | ||
| 1090 | SavePlayerValues(); | 1175 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 1176 | SavePlayerValue(p); | ||
| 1177 | } | ||
| 1091 | SaveDebugValues(); | 1178 | SaveDebugValues(); |
| 1092 | SaveMouseValues(); | 1179 | SaveMouseValues(); |
| 1093 | SaveTouchscreenValues(); | 1180 | SaveTouchscreenValues(); |
| 1094 | SaveMotionTouchValues(); | 1181 | SaveMotionTouchValues(); |
| 1095 | 1182 | ||
| 1096 | WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true); | 1183 | WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); |
| 1097 | WriteSetting(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); | 1184 | WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, |
| 1185 | true); | ||
| 1186 | WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"), | ||
| 1187 | Settings::values.enable_accurate_vibrations, false); | ||
| 1188 | WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); | ||
| 1098 | WriteSetting(QStringLiteral("motion_device"), | 1189 | WriteSetting(QStringLiteral("motion_device"), |
| 1099 | QString::fromStdString(Settings::values.motion_device), | 1190 | QString::fromStdString(Settings::values.motion_device), |
| 1100 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | 1191 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); |
| @@ -1102,7 +1193,6 @@ void Config::SaveControlValues() { | |||
| 1102 | QString::fromStdString(Settings::values.touch_device), | 1193 | QString::fromStdString(Settings::values.touch_device), |
| 1103 | QStringLiteral("engine:emu_window")); | 1194 | QStringLiteral("engine:emu_window")); |
| 1104 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); | 1195 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); |
| 1105 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); | ||
| 1106 | 1196 | ||
| 1107 | qt_config->endGroup(); | 1197 | qt_config->endGroup(); |
| 1108 | } | 1198 | } |
| @@ -1515,3 +1605,19 @@ void Config::Save() { | |||
| 1515 | Settings::Sanitize(); | 1605 | Settings::Sanitize(); |
| 1516 | SaveValues(); | 1606 | SaveValues(); |
| 1517 | } | 1607 | } |
| 1608 | |||
| 1609 | void Config::ReadControlPlayerValue(std::size_t player_index) { | ||
| 1610 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1611 | ReadPlayerValue(player_index); | ||
| 1612 | qt_config->endGroup(); | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | void Config::SaveControlPlayerValue(std::size_t player_index) { | ||
| 1616 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1617 | SavePlayerValue(player_index); | ||
| 1618 | qt_config->endGroup(); | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | const std::string& Config::GetConfigFilePath() const { | ||
| 1622 | return qt_config_loc; | ||
| 1623 | } | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 5d8e45d78..8a600e19d 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -16,12 +16,24 @@ class QSettings; | |||
| 16 | 16 | ||
| 17 | class Config { | 17 | class Config { |
| 18 | public: | 18 | public: |
| 19 | explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true); | 19 | enum class ConfigType { |
| 20 | GlobalConfig, | ||
| 21 | PerGameConfig, | ||
| 22 | InputProfile, | ||
| 23 | }; | ||
| 24 | |||
| 25 | explicit Config(const std::string& config_name = "qt-config", | ||
| 26 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 20 | ~Config(); | 27 | ~Config(); |
| 21 | 28 | ||
| 22 | void Reload(); | 29 | void Reload(); |
| 23 | void Save(); | 30 | void Save(); |
| 24 | 31 | ||
| 32 | void ReadControlPlayerValue(std::size_t player_index); | ||
| 33 | void SaveControlPlayerValue(std::size_t player_index); | ||
| 34 | |||
| 35 | const std::string& GetConfigFilePath() const; | ||
| 36 | |||
| 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | 37 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; |
| 26 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; | 38 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; |
| 27 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; | 39 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; |
| @@ -33,8 +45,10 @@ public: | |||
| 33 | static const std::array<UISettings::Shortcut, 16> default_hotkeys; | 45 | static const std::array<UISettings::Shortcut, 16> default_hotkeys; |
| 34 | 46 | ||
| 35 | private: | 47 | private: |
| 48 | void Initialize(const std::string& config_name); | ||
| 49 | |||
| 36 | void ReadValues(); | 50 | void ReadValues(); |
| 37 | void ReadPlayerValues(); | 51 | void ReadPlayerValue(std::size_t player_index); |
| 38 | void ReadDebugValues(); | 52 | void ReadDebugValues(); |
| 39 | void ReadKeyboardValues(); | 53 | void ReadKeyboardValues(); |
| 40 | void ReadMouseValues(); | 54 | void ReadMouseValues(); |
| @@ -62,7 +76,7 @@ private: | |||
| 62 | void ReadWebServiceValues(); | 76 | void ReadWebServiceValues(); |
| 63 | 77 | ||
| 64 | void SaveValues(); | 78 | void SaveValues(); |
| 65 | void SavePlayerValues(); | 79 | void SavePlayerValue(std::size_t player_index); |
| 66 | void SaveDebugValues(); | 80 | void SaveDebugValues(); |
| 67 | void SaveMouseValues(); | 81 | void SaveMouseValues(); |
| 68 | void SaveTouchscreenValues(); | 82 | void SaveTouchscreenValues(); |
| @@ -111,9 +125,9 @@ private: | |||
| 111 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | 125 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, |
| 112 | const QVariant& default_value); | 126 | const QVariant& default_value); |
| 113 | 127 | ||
| 128 | ConfigType type; | ||
| 114 | std::unique_ptr<QSettings> qt_config; | 129 | std::unique_ptr<QSettings> qt_config; |
| 115 | std::string qt_config_loc; | 130 | std::string qt_config_loc; |
| 116 | |||
| 117 | bool global; | 131 | bool global; |
| 118 | }; | 132 | }; |
| 119 | 133 | ||
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index fcf42cdcb..f92c3aff3 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -275,32 +275,12 @@ | |||
| 275 | <signal>accepted()</signal> | 275 | <signal>accepted()</signal> |
| 276 | <receiver>ConfigureDialog</receiver> | 276 | <receiver>ConfigureDialog</receiver> |
| 277 | <slot>accept()</slot> | 277 | <slot>accept()</slot> |
| 278 | <hints> | ||
| 279 | <hint type="sourcelabel"> | ||
| 280 | <x>220</x> | ||
| 281 | <y>380</y> | ||
| 282 | </hint> | ||
| 283 | <hint type="destinationlabel"> | ||
| 284 | <x>220</x> | ||
| 285 | <y>200</y> | ||
| 286 | </hint> | ||
| 287 | </hints> | ||
| 288 | </connection> | 278 | </connection> |
| 289 | <connection> | 279 | <connection> |
| 290 | <sender>buttonBox</sender> | 280 | <sender>buttonBox</sender> |
| 291 | <signal>rejected()</signal> | 281 | <signal>rejected()</signal> |
| 292 | <receiver>ConfigureDialog</receiver> | 282 | <receiver>ConfigureDialog</receiver> |
| 293 | <slot>reject()</slot> | 283 | <slot>reject()</slot> |
| 294 | <hints> | ||
| 295 | <hint type="sourcelabel"> | ||
| 296 | <x>220</x> | ||
| 297 | <y>380</y> | ||
| 298 | </hint> | ||
| 299 | <hint type="destinationlabel"> | ||
| 300 | <x>220</x> | ||
| 301 | <y>200</y> | ||
| 302 | </hint> | ||
| 303 | </hints> | ||
| 304 | </connection> | 284 | </connection> |
| 305 | </connections> | 285 | </connections> |
| 306 | </ui> | 286 | </ui> |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 2bfe2c306..027099ab7 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -41,6 +41,7 @@ void ConfigureDebug::SetConfiguration() { | |||
| 41 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); | 41 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); |
| 42 | ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | 42 | ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); |
| 43 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit); | 43 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit); |
| 44 | ui->extended_logging->setChecked(Settings::values.extended_logging); | ||
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | void ConfigureDebug::ApplyConfiguration() { | 47 | void ConfigureDebug::ApplyConfiguration() { |
| @@ -53,6 +54,7 @@ void ConfigureDebug::ApplyConfiguration() { | |||
| 53 | Settings::values.quest_flag = ui->quest_flag->isChecked(); | 54 | Settings::values.quest_flag = ui->quest_flag->isChecked(); |
| 54 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); | 55 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); |
| 55 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); | 56 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); |
| 57 | Settings::values.extended_logging = ui->extended_logging->isChecked(); | ||
| 56 | Debugger::ToggleConsole(); | 58 | Debugger::ToggleConsole(); |
| 57 | Log::Filter filter; | 59 | Log::Filter filter; |
| 58 | filter.ParseFilterString(Settings::values.log_filter); | 60 | filter.ParseFilterString(Settings::values.log_filter); |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 9d6feb9f7..6f94fe304 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -90,7 +90,7 @@ | |||
| 90 | <item> | 90 | <item> |
| 91 | <widget class="QCheckBox" name="toggle_console"> | 91 | <widget class="QCheckBox" name="toggle_console"> |
| 92 | <property name="text"> | 92 | <property name="text"> |
| 93 | <string>Show Log Console (Windows Only)</string> | 93 | <string>Show Log in Console</string> |
| 94 | </property> | 94 | </property> |
| 95 | </widget> | 95 | </widget> |
| 96 | </item> | 96 | </item> |
| @@ -103,6 +103,34 @@ | |||
| 103 | </item> | 103 | </item> |
| 104 | </layout> | 104 | </layout> |
| 105 | </item> | 105 | </item> |
| 106 | <item> | ||
| 107 | <widget class="QCheckBox" name="extended_logging"> | ||
| 108 | <property name="enabled"> | ||
| 109 | <bool>true</bool> | ||
| 110 | </property> | ||
| 111 | <property name="toolTip"> | ||
| 112 | <string>When checked, the max size of the log increases from 100 MB to 1 GB</string> | ||
| 113 | </property> | ||
| 114 | <property name="text"> | ||
| 115 | <string>Enable Extended Logging</string> | ||
| 116 | </property> | ||
| 117 | </widget> | ||
| 118 | </item> | ||
| 119 | <item> | ||
| 120 | <widget class="QLabel" name="label_3"> | ||
| 121 | <property name="font"> | ||
| 122 | <font> | ||
| 123 | <italic>true</italic> | ||
| 124 | </font> | ||
| 125 | </property> | ||
| 126 | <property name="text"> | ||
| 127 | <string>This will be reset automatically when yuzu closes.</string> | ||
| 128 | </property> | ||
| 129 | <property name="indent"> | ||
| 130 | <number>20</number> | ||
| 131 | </property> | ||
| 132 | </widget> | ||
| 133 | </item> | ||
| 106 | </layout> | 134 | </layout> |
| 107 | </widget> | 135 | </widget> |
| 108 | </item> | 136 | </item> |
| @@ -115,7 +143,7 @@ | |||
| 115 | <item> | 143 | <item> |
| 116 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | 144 | <layout class="QHBoxLayout" name="horizontalLayout_4"> |
| 117 | <item> | 145 | <item> |
| 118 | <widget class="QLabel" name="label_3"> | 146 | <widget class="QLabel" name="label_4"> |
| 119 | <property name="text"> | 147 | <property name="text"> |
| 120 | <string>Arguments String</string> | 148 | <string>Arguments String</string> |
| 121 | </property> | 149 | </property> |
| @@ -140,8 +168,8 @@ | |||
| 140 | <property name="enabled"> | 168 | <property name="enabled"> |
| 141 | <bool>true</bool> | 169 | <bool>true</bool> |
| 142 | </property> | 170 | </property> |
| 143 | <property name="whatsThis"> | 171 | <property name="toolTip"> |
| 144 | <string>When checked, the graphics API enters in a slower debugging mode</string> | 172 | <string>When checked, the graphics API enters a slower debugging mode</string> |
| 145 | </property> | 173 | </property> |
| 146 | <property name="text"> | 174 | <property name="text"> |
| 147 | <string>Enable Graphics Debugging</string> | 175 | <string>Enable Graphics Debugging</string> |
| @@ -153,8 +181,8 @@ | |||
| 153 | <property name="enabled"> | 181 | <property name="enabled"> |
| 154 | <bool>true</bool> | 182 | <bool>true</bool> |
| 155 | </property> | 183 | </property> |
| 156 | <property name="whatsThis"> | 184 | <property name="toolTip"> |
| 157 | <string>When checked, it disables the macro Just In Time compiler. Enabled this makes games run slower</string> | 185 | <string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string> |
| 158 | </property> | 186 | </property> |
| 159 | <property name="text"> | 187 | <property name="text"> |
| 160 | <string>Disable Macro JIT</string> | 188 | <string>Disable Macro JIT</string> |
| @@ -169,7 +197,7 @@ | |||
| 169 | <property name="title"> | 197 | <property name="title"> |
| 170 | <string>Dump</string> | 198 | <string>Dump</string> |
| 171 | </property> | 199 | </property> |
| 172 | <layout class="QVBoxLayout" name="verticalLayout_6"> | 200 | <layout class="QVBoxLayout" name="verticalLayout_7"> |
| 173 | <item> | 201 | <item> |
| 174 | <widget class="QCheckBox" name="reporting_services"> | 202 | <widget class="QCheckBox" name="reporting_services"> |
| 175 | <property name="text"> | 203 | <property name="text"> |
| @@ -178,7 +206,7 @@ | |||
| 178 | </widget> | 206 | </widget> |
| 179 | </item> | 207 | </item> |
| 180 | <item> | 208 | <item> |
| 181 | <widget class="QLabel" name="label"> | 209 | <widget class="QLabel" name="label_5"> |
| 182 | <property name="font"> | 210 | <property name="font"> |
| 183 | <font> | 211 | <font> |
| 184 | <italic>true</italic> | 212 | <italic>true</italic> |
| @@ -200,7 +228,7 @@ | |||
| 200 | <property name="title"> | 228 | <property name="title"> |
| 201 | <string>Advanced</string> | 229 | <string>Advanced</string> |
| 202 | </property> | 230 | </property> |
| 203 | <layout class="QVBoxLayout" name="verticalLayout_7"> | 231 | <layout class="QVBoxLayout" name="verticalLayout_8"> |
| 204 | <item> | 232 | <item> |
| 205 | <widget class="QCheckBox" name="quest_flag"> | 233 | <widget class="QCheckBox" name="quest_flag"> |
| 206 | <property name="text"> | 234 | <property name="text"> |
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp index 0097c9a29..a878ef9c6 100644 --- a/src/yuzu/configuration/configure_debug_controller.cpp +++ b/src/yuzu/configuration/configure_debug_controller.cpp | |||
| @@ -4,11 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include "ui_configure_debug_controller.h" | 5 | #include "ui_configure_debug_controller.h" |
| 6 | #include "yuzu/configuration/configure_debug_controller.h" | 6 | #include "yuzu/configuration/configure_debug_controller.h" |
| 7 | #include "yuzu/configuration/configure_input_player.h" | ||
| 7 | 8 | ||
| 8 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, | 9 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, |
| 9 | InputCommon::InputSubsystem* input_subsystem) | 10 | InputCommon::InputSubsystem* input_subsystem, |
| 11 | InputProfiles* profiles) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), | 12 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), |
| 11 | debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) { | 13 | debug_controller( |
| 14 | new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, true)) { | ||
| 12 | ui->setupUi(this); | 15 | ui->setupUi(this); |
| 13 | 16 | ||
| 14 | ui->controllerLayout->addWidget(debug_controller); | 17 | ui->controllerLayout->addWidget(debug_controller); |
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h index 34dcf705f..b4f53fad5 100644 --- a/src/yuzu/configuration/configure_debug_controller.h +++ b/src/yuzu/configuration/configure_debug_controller.h | |||
| @@ -6,10 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QDialog> | 8 | #include <QDialog> |
| 9 | #include "yuzu/configuration/configure_input_player.h" | ||
| 10 | 9 | ||
| 11 | class QPushButton; | 10 | class QPushButton; |
| 12 | 11 | ||
| 12 | class ConfigureInputPlayer; | ||
| 13 | |||
| 14 | class InputProfiles; | ||
| 15 | |||
| 13 | namespace InputCommon { | 16 | namespace InputCommon { |
| 14 | class InputSubsystem; | 17 | class InputSubsystem; |
| 15 | } | 18 | } |
| @@ -22,8 +25,8 @@ class ConfigureDebugController : public QDialog { | |||
| 22 | Q_OBJECT | 25 | Q_OBJECT |
| 23 | 26 | ||
| 24 | public: | 27 | public: |
| 25 | explicit ConfigureDebugController(QWidget* parent, | 28 | explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem, |
| 26 | InputCommon::InputSubsystem* input_subsystem); | 29 | InputProfiles* profiles); |
| 27 | ~ConfigureDebugController() override; | 30 | ~ConfigureDebugController() override; |
| 28 | 31 | ||
| 29 | void ApplyConfiguration(); | 32 | void ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_debug_controller.ui b/src/yuzu/configuration/configure_debug_controller.ui index a95ed50ff..7b7e6582c 100644 --- a/src/yuzu/configuration/configure_debug_controller.ui +++ b/src/yuzu/configuration/configure_debug_controller.ui | |||
| @@ -66,32 +66,12 @@ | |||
| 66 | <signal>accepted()</signal> | 66 | <signal>accepted()</signal> |
| 67 | <receiver>ConfigureDebugController</receiver> | 67 | <receiver>ConfigureDebugController</receiver> |
| 68 | <slot>accept()</slot> | 68 | <slot>accept()</slot> |
| 69 | <hints> | ||
| 70 | <hint type="sourcelabel"> | ||
| 71 | <x>140</x> | ||
| 72 | <y>318</y> | ||
| 73 | </hint> | ||
| 74 | <hint type="destinationlabel"> | ||
| 75 | <x>140</x> | ||
| 76 | <y>169</y> | ||
| 77 | </hint> | ||
| 78 | </hints> | ||
| 79 | </connection> | 69 | </connection> |
| 80 | <connection> | 70 | <connection> |
| 81 | <sender>buttonBox</sender> | 71 | <sender>buttonBox</sender> |
| 82 | <signal>rejected()</signal> | 72 | <signal>rejected()</signal> |
| 83 | <receiver>ConfigureDebugController</receiver> | 73 | <receiver>ConfigureDebugController</receiver> |
| 84 | <slot>reject()</slot> | 74 | <slot>reject()</slot> |
| 85 | <hints> | ||
| 86 | <hint type="sourcelabel"> | ||
| 87 | <x>140</x> | ||
| 88 | <y>318</y> | ||
| 89 | </hint> | ||
| 90 | <hint type="destinationlabel"> | ||
| 91 | <x>140</x> | ||
| 92 | <y>169</y> | ||
| 93 | </hint> | ||
| 94 | </hints> | ||
| 95 | </connection> | 75 | </connection> |
| 96 | </connections> | 76 | </connections> |
| 97 | </ui> | 77 | </ui> |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 2725fcb2b..d9009091b 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include "yuzu/configuration/configure_motion_touch.h" | 23 | #include "yuzu/configuration/configure_motion_touch.h" |
| 24 | #include "yuzu/configuration/configure_mouse_advanced.h" | 24 | #include "yuzu/configuration/configure_mouse_advanced.h" |
| 25 | #include "yuzu/configuration/configure_touchscreen_advanced.h" | 25 | #include "yuzu/configuration/configure_touchscreen_advanced.h" |
| 26 | #include "yuzu/configuration/configure_vibration.h" | ||
| 27 | #include "yuzu/configuration/input_profiles.h" | ||
| 26 | 28 | ||
| 27 | namespace { | 29 | namespace { |
| 28 | template <typename Dialog, typename... Args> | 30 | template <typename Dialog, typename... Args> |
| @@ -64,7 +66,8 @@ void OnDockedModeChanged(bool last_state, bool new_state) { | |||
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | ConfigureInput::ConfigureInput(QWidget* parent) | 68 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 67 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | 69 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), |
| 70 | profiles(std::make_unique<InputProfiles>()) { | ||
| 68 | ui->setupUi(this); | 71 | ui->setupUi(this); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| @@ -73,14 +76,22 @@ ConfigureInput::~ConfigureInput() = default; | |||
| 73 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | 76 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, |
| 74 | std::size_t max_players) { | 77 | std::size_t max_players) { |
| 75 | player_controllers = { | 78 | player_controllers = { |
| 76 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), | 79 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, |
| 77 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), | 80 | profiles.get()), |
| 78 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem), | 81 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem, |
| 79 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem), | 82 | profiles.get()), |
| 80 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem), | 83 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem, |
| 81 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem), | 84 | profiles.get()), |
| 82 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem), | 85 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem, |
| 83 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem), | 86 | profiles.get()), |
| 87 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem, | ||
| 88 | profiles.get()), | ||
| 89 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem, | ||
| 90 | profiles.get()), | ||
| 91 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem, | ||
| 92 | profiles.get()), | ||
| 93 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem, | ||
| 94 | profiles.get()), | ||
| 84 | }; | 95 | }; |
| 85 | 96 | ||
| 86 | player_tabs = { | 97 | player_tabs = { |
| @@ -113,8 +124,10 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 113 | } | 124 | } |
| 114 | } | 125 | } |
| 115 | }); | 126 | }); |
| 116 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, | 127 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this, |
| 117 | [this] { UpdateAllInputDevices(); }); | 128 | &ConfigureInput::UpdateAllInputDevices); |
| 129 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this, | ||
| 130 | &ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection); | ||
| 118 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { | 131 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { |
| 119 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); | 132 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); |
| 120 | }); | 133 | }); |
| @@ -134,7 +147,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 134 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); | 147 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); |
| 135 | ui->tabAdvanced->layout()->addWidget(advanced); | 148 | ui->tabAdvanced->layout()->addWidget(advanced); |
| 136 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { | 149 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { |
| 137 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem); | 150 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get()); |
| 138 | }); | 151 | }); |
| 139 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { | 152 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { |
| 140 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); | 153 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); |
| @@ -146,6 +159,9 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 146 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); | 159 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); |
| 147 | }); | 160 | }); |
| 148 | 161 | ||
| 162 | connect(ui->vibrationButton, &QPushButton::clicked, | ||
| 163 | [this] { CallConfigureDialog<ConfigureVibration>(*this); }); | ||
| 164 | |||
| 149 | connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { | 165 | connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { |
| 150 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); | 166 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); |
| 151 | }); | 167 | }); |
| @@ -171,12 +187,12 @@ void ConfigureInput::ApplyConfiguration() { | |||
| 171 | 187 | ||
| 172 | advanced->ApplyConfiguration(); | 188 | advanced->ApplyConfiguration(); |
| 173 | 189 | ||
| 174 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 190 | const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); |
| 175 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); | 191 | Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()); |
| 176 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 192 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue()); |
| 177 | 193 | ||
| 178 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); | 194 | Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); |
| 179 | Settings::values.motion_enabled = ui->motionGroup->isChecked(); | 195 | Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); |
| 180 | } | 196 | } |
| 181 | 197 | ||
| 182 | void ConfigureInput::changeEvent(QEvent* event) { | 198 | void ConfigureInput::changeEvent(QEvent* event) { |
| @@ -193,16 +209,16 @@ void ConfigureInput::RetranslateUI() { | |||
| 193 | 209 | ||
| 194 | void ConfigureInput::LoadConfiguration() { | 210 | void ConfigureInput::LoadConfiguration() { |
| 195 | LoadPlayerControllerIndices(); | 211 | LoadPlayerControllerIndices(); |
| 196 | UpdateDockedState(Settings::values.players[8].connected); | 212 | UpdateDockedState(Settings::values.players.GetValue()[8].connected); |
| 197 | 213 | ||
| 198 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); | 214 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); |
| 199 | ui->motionGroup->setChecked(Settings::values.motion_enabled); | 215 | ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); |
| 200 | } | 216 | } |
| 201 | 217 | ||
| 202 | void ConfigureInput::LoadPlayerControllerIndices() { | 218 | void ConfigureInput::LoadPlayerControllerIndices() { |
| 203 | for (std::size_t i = 0; i < player_connected.size(); ++i) { | 219 | for (std::size_t i = 0; i < player_connected.size(); ++i) { |
| 204 | const auto connected = Settings::values.players[i].connected || | 220 | const auto connected = Settings::values.players.GetValue()[i].connected || |
| 205 | (i == 0 && Settings::values.players[8].connected); | 221 | (i == 0 && Settings::values.players.GetValue()[8].connected); |
| 206 | player_connected[i]->setChecked(connected); | 222 | player_connected[i]->setChecked(connected); |
| 207 | } | 223 | } |
| 208 | } | 224 | } |
| @@ -231,8 +247,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) { | |||
| 231 | ui->radioDocked->setEnabled(!is_handheld); | 247 | ui->radioDocked->setEnabled(!is_handheld); |
| 232 | ui->radioUndocked->setEnabled(!is_handheld); | 248 | ui->radioUndocked->setEnabled(!is_handheld); |
| 233 | 249 | ||
| 234 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); | 250 | ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 235 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); | 251 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue()); |
| 236 | 252 | ||
| 237 | // Also force into undocked mode if the controller type is handheld. | 253 | // Also force into undocked mode if the controller type is handheld. |
| 238 | if (is_handheld) { | 254 | if (is_handheld) { |
| @@ -242,6 +258,16 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) { | |||
| 242 | 258 | ||
| 243 | void ConfigureInput::UpdateAllInputDevices() { | 259 | void ConfigureInput::UpdateAllInputDevices() { |
| 244 | for (const auto& player : player_controllers) { | 260 | for (const auto& player : player_controllers) { |
| 245 | player->UpdateInputDevices(); | 261 | player->UpdateInputDeviceCombobox(); |
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | void ConfigureInput::UpdateAllInputProfiles(std::size_t player_index) { | ||
| 266 | for (std::size_t i = 0; i < player_controllers.size(); ++i) { | ||
| 267 | if (i == player_index) { | ||
| 268 | continue; | ||
| 269 | } | ||
| 270 | |||
| 271 | player_controllers[i]->UpdateInputProfiles(); | ||
| 246 | } | 272 | } |
| 247 | } | 273 | } |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 0e8b2fd4e..f4eb0d78b 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -8,17 +8,18 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | 9 | ||
| 10 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QList> | ||
| 11 | #include <QWidget> | 12 | #include <QWidget> |
| 12 | 13 | ||
| 13 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 14 | #include "yuzu/configuration/configure_input_player.h" | ||
| 15 | |||
| 16 | #include "ui_configure_input.h" | ||
| 17 | |||
| 18 | class QCheckBox; | 14 | class QCheckBox; |
| 19 | class QString; | 15 | class QString; |
| 20 | class QTimer; | 16 | class QTimer; |
| 21 | 17 | ||
| 18 | class ConfigureInputAdvanced; | ||
| 19 | class ConfigureInputPlayer; | ||
| 20 | |||
| 21 | class InputProfiles; | ||
| 22 | |||
| 22 | namespace InputCommon { | 23 | namespace InputCommon { |
| 23 | class InputSubsystem; | 24 | class InputSubsystem; |
| 24 | } | 25 | } |
| @@ -51,6 +52,7 @@ private: | |||
| 51 | 52 | ||
| 52 | void UpdateDockedState(bool is_handheld); | 53 | void UpdateDockedState(bool is_handheld); |
| 53 | void UpdateAllInputDevices(); | 54 | void UpdateAllInputDevices(); |
| 55 | void UpdateAllInputProfiles(std::size_t player_index); | ||
| 54 | 56 | ||
| 55 | /// Load configuration settings. | 57 | /// Load configuration settings. |
| 56 | void LoadConfiguration(); | 58 | void LoadConfiguration(); |
| @@ -61,6 +63,8 @@ private: | |||
| 61 | 63 | ||
| 62 | std::unique_ptr<Ui::ConfigureInput> ui; | 64 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 63 | 65 | ||
| 66 | std::unique_ptr<InputProfiles> profiles; | ||
| 67 | |||
| 64 | std::array<ConfigureInputPlayer*, 8> player_controllers; | 68 | std::array<ConfigureInputPlayer*, 8> player_controllers; |
| 65 | std::array<QWidget*, 8> player_tabs; | 69 | std::array<QWidget*, 8> player_tabs; |
| 66 | std::array<QCheckBox*, 8> player_connected; | 70 | std::array<QCheckBox*, 8> player_connected; |
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 136955224..2707025e7 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>700</width> | 9 | <width>680</width> |
| 10 | <height>540</height> | 10 | <height>540</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| @@ -142,7 +142,7 @@ | |||
| 142 | <number>6</number> | 142 | <number>6</number> |
| 143 | </property> | 143 | </property> |
| 144 | <property name="leftMargin"> | 144 | <property name="leftMargin"> |
| 145 | <number>3</number> | 145 | <number>8</number> |
| 146 | </property> | 146 | </property> |
| 147 | <property name="topMargin"> | 147 | <property name="topMargin"> |
| 148 | <number>6</number> | 148 | <number>6</number> |
| @@ -195,30 +195,24 @@ | |||
| 195 | <number>3</number> | 195 | <number>3</number> |
| 196 | </property> | 196 | </property> |
| 197 | <item> | 197 | <item> |
| 198 | <widget class="QSpinBox" name="vibrationSpin"> | 198 | <widget class="QPushButton" name="vibrationButton"> |
| 199 | <property name="minimumSize"> | 199 | <property name="minimumSize"> |
| 200 | <size> | 200 | <size> |
| 201 | <width>65</width> | 201 | <width>68</width> |
| 202 | <height>21</height> | 202 | <height>0</height> |
| 203 | </size> | 203 | </size> |
| 204 | </property> | 204 | </property> |
| 205 | <property name="maximumSize"> | 205 | <property name="maximumSize"> |
| 206 | <size> | 206 | <size> |
| 207 | <width>65</width> | 207 | <width>68</width> |
| 208 | <height>16777215</height> | 208 | <height>16777215</height> |
| 209 | </size> | 209 | </size> |
| 210 | </property> | 210 | </property> |
| 211 | <property name="suffix"> | 211 | <property name="styleSheet"> |
| 212 | <string>%</string> | 212 | <string notr="true">min-width: 68px;</string> |
| 213 | </property> | ||
| 214 | <property name="minimum"> | ||
| 215 | <number>1</number> | ||
| 216 | </property> | ||
| 217 | <property name="maximum"> | ||
| 218 | <number>200</number> | ||
| 219 | </property> | 213 | </property> |
| 220 | <property name="value"> | 214 | <property name="text"> |
| 221 | <number>100</number> | 215 | <string>Configure</string> |
| 222 | </property> | 216 | </property> |
| 223 | </widget> | 217 | </widget> |
| 224 | </item> | 218 | </item> |
| @@ -250,18 +244,18 @@ | |||
| 250 | <widget class="QPushButton" name="motionButton"> | 244 | <widget class="QPushButton" name="motionButton"> |
| 251 | <property name="minimumSize"> | 245 | <property name="minimumSize"> |
| 252 | <size> | 246 | <size> |
| 253 | <width>57</width> | 247 | <width>68</width> |
| 254 | <height>0</height> | 248 | <height>0</height> |
| 255 | </size> | 249 | </size> |
| 256 | </property> | 250 | </property> |
| 257 | <property name="maximumSize"> | 251 | <property name="maximumSize"> |
| 258 | <size> | 252 | <size> |
| 259 | <width>55</width> | 253 | <width>68</width> |
| 260 | <height>16777215</height> | 254 | <height>16777215</height> |
| 261 | </size> | 255 | </size> |
| 262 | </property> | 256 | </property> |
| 263 | <property name="styleSheet"> | 257 | <property name="styleSheet"> |
| 264 | <string notr="true">min-width: 55px;</string> | 258 | <string notr="true">min-width: 68px;</string> |
| 265 | </property> | 259 | </property> |
| 266 | <property name="text"> | 260 | <property name="text"> |
| 267 | <string>Configure</string> | 261 | <string>Configure</string> |
| @@ -272,7 +266,7 @@ | |||
| 272 | </widget> | 266 | </widget> |
| 273 | </item> | 267 | </item> |
| 274 | <item alignment="Qt::AlignVCenter"> | 268 | <item alignment="Qt::AlignVCenter"> |
| 275 | <widget class="QWidget" name="widget" native="true"> | 269 | <widget class="QWidget" name="connectedControllers" native="true"> |
| 276 | <layout class="QGridLayout" name="gridLayout_2"> | 270 | <layout class="QGridLayout" name="gridLayout_2"> |
| 277 | <property name="leftMargin"> | 271 | <property name="leftMargin"> |
| 278 | <number>5</number> | 272 | <number>5</number> |
| @@ -468,13 +462,13 @@ | |||
| 468 | </property> | 462 | </property> |
| 469 | <property name="minimumSize"> | 463 | <property name="minimumSize"> |
| 470 | <size> | 464 | <size> |
| 471 | <width>57</width> | 465 | <width>68</width> |
| 472 | <height>0</height> | 466 | <height>0</height> |
| 473 | </size> | 467 | </size> |
| 474 | </property> | 468 | </property> |
| 475 | <property name="maximumSize"> | 469 | <property name="maximumSize"> |
| 476 | <size> | 470 | <size> |
| 477 | <width>55</width> | 471 | <width>68</width> |
| 478 | <height>16777215</height> | 472 | <height>16777215</height> |
| 479 | </size> | 473 | </size> |
| 480 | </property> | 474 | </property> |
| @@ -494,7 +488,7 @@ | |||
| 494 | <enum>Qt::LeftToRight</enum> | 488 | <enum>Qt::LeftToRight</enum> |
| 495 | </property> | 489 | </property> |
| 496 | <property name="styleSheet"> | 490 | <property name="styleSheet"> |
| 497 | <string notr="true">min-width: 55px;</string> | 491 | <string notr="true">min-width: 68px;</string> |
| 498 | </property> | 492 | </property> |
| 499 | <property name="text"> | 493 | <property name="text"> |
| 500 | <string>Defaults</string> | 494 | <string>Defaults</string> |
| @@ -511,13 +505,13 @@ | |||
| 511 | </property> | 505 | </property> |
| 512 | <property name="minimumSize"> | 506 | <property name="minimumSize"> |
| 513 | <size> | 507 | <size> |
| 514 | <width>57</width> | 508 | <width>68</width> |
| 515 | <height>0</height> | 509 | <height>0</height> |
| 516 | </size> | 510 | </size> |
| 517 | </property> | 511 | </property> |
| 518 | <property name="maximumSize"> | 512 | <property name="maximumSize"> |
| 519 | <size> | 513 | <size> |
| 520 | <width>55</width> | 514 | <width>68</width> |
| 521 | <height>16777215</height> | 515 | <height>16777215</height> |
| 522 | </size> | 516 | </size> |
| 523 | </property> | 517 | </property> |
| @@ -537,7 +531,7 @@ | |||
| 537 | <enum>Qt::LeftToRight</enum> | 531 | <enum>Qt::LeftToRight</enum> |
| 538 | </property> | 532 | </property> |
| 539 | <property name="styleSheet"> | 533 | <property name="styleSheet"> |
| 540 | <string notr="true">min-width: 55px;</string> | 534 | <string notr="true">min-width: 68px;</string> |
| 541 | </property> | 535 | </property> |
| 542 | <property name="text"> | 536 | <property name="text"> |
| 543 | <string>Clear</string> | 537 | <string>Clear</string> |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 81f9dc16c..abaf03630 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -68,8 +68,7 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | |||
| 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { | 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { |
| 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, | 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, |
| 70 | [this, player_idx, button_idx] { | 70 | [this, player_idx, button_idx] { |
| 71 | OnControllerButtonClick(static_cast<int>(player_idx), | 71 | OnControllerButtonClick(player_idx, button_idx); |
| 72 | static_cast<int>(button_idx)); | ||
| 73 | }); | 72 | }); |
| 74 | } | 73 | } |
| 75 | } | 74 | } |
| @@ -94,20 +93,21 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | |||
| 94 | 93 | ||
| 95 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; | 94 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; |
| 96 | 95 | ||
| 97 | void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) { | 96 | void ConfigureInputAdvanced::OnControllerButtonClick(std::size_t player_idx, |
| 97 | std::size_t button_idx) { | ||
| 98 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); | 98 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); |
| 99 | if (!new_bg_color.isValid()) { | 99 | if (!new_bg_color.isValid()) { |
| 100 | return; | 100 | return; |
| 101 | } | 101 | } |
| 102 | controllers_colors[player_idx][button_idx] = new_bg_color; | 102 | controllers_colors[player_idx][button_idx] = new_bg_color; |
| 103 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | 103 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( |
| 104 | QStringLiteral("background-color: %1; min-width: 55px;") | 104 | QStringLiteral("background-color: %1; min-width: 60px;") |
| 105 | .arg(controllers_colors[player_idx][button_idx].name())); | 105 | .arg(controllers_colors[player_idx][button_idx].name())); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ConfigureInputAdvanced::ApplyConfiguration() { | 108 | void ConfigureInputAdvanced::ApplyConfiguration() { |
| 109 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | 109 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { |
| 110 | auto& player = Settings::values.players[player_idx]; | 110 | auto& player = Settings::values.players.GetValue()[player_idx]; |
| 111 | std::array<u32, 4> colors{}; | 111 | std::array<u32, 4> colors{}; |
| 112 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), | 112 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), |
| 113 | colors.begin(), [](QColor color) { return color.rgb(); }); | 113 | colors.begin(), [](QColor color) { return color.rgb(); }); |
| @@ -126,7 +126,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() { | |||
| 126 | 126 | ||
| 127 | void ConfigureInputAdvanced::LoadConfiguration() { | 127 | void ConfigureInputAdvanced::LoadConfiguration() { |
| 128 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | 128 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { |
| 129 | auto& player = Settings::values.players[player_idx]; | 129 | auto& player = Settings::values.players.GetValue()[player_idx]; |
| 130 | std::array<u32, 4> colors = { | 130 | std::array<u32, 4> colors = { |
| 131 | player.body_color_left, | 131 | player.body_color_left, |
| 132 | player.button_color_left, | 132 | player.button_color_left, |
| @@ -139,7 +139,7 @@ void ConfigureInputAdvanced::LoadConfiguration() { | |||
| 139 | 139 | ||
| 140 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { | 140 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { |
| 141 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | 141 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( |
| 142 | QStringLiteral("background-color: %1; min-width: 55px;") | 142 | QStringLiteral("background-color: %1; min-width: 60px;") |
| 143 | .arg(controllers_colors[player_idx][button_idx].name())); | 143 | .arg(controllers_colors[player_idx][button_idx].name())); |
| 144 | } | 144 | } |
| 145 | } | 145 | } |
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h index 50bb87768..3083d55c1 100644 --- a/src/yuzu/configuration/configure_input_advanced.h +++ b/src/yuzu/configuration/configure_input_advanced.h | |||
| @@ -35,7 +35,7 @@ private: | |||
| 35 | void RetranslateUI(); | 35 | void RetranslateUI(); |
| 36 | void UpdateUIEnabled(); | 36 | void UpdateUIEnabled(); |
| 37 | 37 | ||
| 38 | void OnControllerButtonClick(int player_idx, int button_idx); | 38 | void OnControllerButtonClick(std::size_t player_idx, std::size_t button_idx); |
| 39 | 39 | ||
| 40 | void LoadConfiguration(); | 40 | void LoadConfiguration(); |
| 41 | 41 | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 5958435fc..a880a7c68 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui | |||
| @@ -192,18 +192,18 @@ | |||
| 192 | </property> | 192 | </property> |
| 193 | <property name="minimumSize"> | 193 | <property name="minimumSize"> |
| 194 | <size> | 194 | <size> |
| 195 | <width>57</width> | 195 | <width>68</width> |
| 196 | <height>0</height> | 196 | <height>0</height> |
| 197 | </size> | 197 | </size> |
| 198 | </property> | 198 | </property> |
| 199 | <property name="maximumSize"> | 199 | <property name="maximumSize"> |
| 200 | <size> | 200 | <size> |
| 201 | <width>55</width> | 201 | <width>68</width> |
| 202 | <height>16777215</height> | 202 | <height>16777215</height> |
| 203 | </size> | 203 | </size> |
| 204 | </property> | 204 | </property> |
| 205 | <property name="styleSheet"> | 205 | <property name="styleSheet"> |
| 206 | <string notr="true">min-width: 55px;</string> | 206 | <string notr="true">min-width: 68px;</string> |
| 207 | </property> | 207 | </property> |
| 208 | <property name="text"> | 208 | <property name="text"> |
| 209 | <string/> | 209 | <string/> |
| @@ -247,18 +247,18 @@ | |||
| 247 | </property> | 247 | </property> |
| 248 | <property name="minimumSize"> | 248 | <property name="minimumSize"> |
| 249 | <size> | 249 | <size> |
| 250 | <width>57</width> | 250 | <width>68</width> |
| 251 | <height>0</height> | 251 | <height>0</height> |
| 252 | </size> | 252 | </size> |
| 253 | </property> | 253 | </property> |
| 254 | <property name="maximumSize"> | 254 | <property name="maximumSize"> |
| 255 | <size> | 255 | <size> |
| 256 | <width>55</width> | 256 | <width>68</width> |
| 257 | <height>16777215</height> | 257 | <height>16777215</height> |
| 258 | </size> | 258 | </size> |
| 259 | </property> | 259 | </property> |
| 260 | <property name="styleSheet"> | 260 | <property name="styleSheet"> |
| 261 | <string notr="true">min-width: 55px;</string> | 261 | <string notr="true">min-width: 68px;</string> |
| 262 | </property> | 262 | </property> |
| 263 | <property name="text"> | 263 | <property name="text"> |
| 264 | <string/> | 264 | <string/> |
| @@ -323,18 +323,18 @@ | |||
| 323 | </property> | 323 | </property> |
| 324 | <property name="minimumSize"> | 324 | <property name="minimumSize"> |
| 325 | <size> | 325 | <size> |
| 326 | <width>57</width> | 326 | <width>68</width> |
| 327 | <height>0</height> | 327 | <height>0</height> |
| 328 | </size> | 328 | </size> |
| 329 | </property> | 329 | </property> |
| 330 | <property name="maximumSize"> | 330 | <property name="maximumSize"> |
| 331 | <size> | 331 | <size> |
| 332 | <width>55</width> | 332 | <width>68</width> |
| 333 | <height>16777215</height> | 333 | <height>16777215</height> |
| 334 | </size> | 334 | </size> |
| 335 | </property> | 335 | </property> |
| 336 | <property name="styleSheet"> | 336 | <property name="styleSheet"> |
| 337 | <string notr="true">min-width: 55px;</string> | 337 | <string notr="true">min-width: 68px;</string> |
| 338 | </property> | 338 | </property> |
| 339 | <property name="text"> | 339 | <property name="text"> |
| 340 | <string/> | 340 | <string/> |
| @@ -378,18 +378,18 @@ | |||
| 378 | </property> | 378 | </property> |
| 379 | <property name="minimumSize"> | 379 | <property name="minimumSize"> |
| 380 | <size> | 380 | <size> |
| 381 | <width>57</width> | 381 | <width>68</width> |
| 382 | <height>0</height> | 382 | <height>0</height> |
| 383 | </size> | 383 | </size> |
| 384 | </property> | 384 | </property> |
| 385 | <property name="maximumSize"> | 385 | <property name="maximumSize"> |
| 386 | <size> | 386 | <size> |
| 387 | <width>55</width> | 387 | <width>68</width> |
| 388 | <height>16777215</height> | 388 | <height>16777215</height> |
| 389 | </size> | 389 | </size> |
| 390 | </property> | 390 | </property> |
| 391 | <property name="styleSheet"> | 391 | <property name="styleSheet"> |
| 392 | <string notr="true">min-width: 55px;</string> | 392 | <string notr="true">min-width: 68px;</string> |
| 393 | </property> | 393 | </property> |
| 394 | <property name="text"> | 394 | <property name="text"> |
| 395 | <string/> | 395 | <string/> |
| @@ -478,18 +478,18 @@ | |||
| 478 | </property> | 478 | </property> |
| 479 | <property name="minimumSize"> | 479 | <property name="minimumSize"> |
| 480 | <size> | 480 | <size> |
| 481 | <width>57</width> | 481 | <width>68</width> |
| 482 | <height>0</height> | 482 | <height>0</height> |
| 483 | </size> | 483 | </size> |
| 484 | </property> | 484 | </property> |
| 485 | <property name="maximumSize"> | 485 | <property name="maximumSize"> |
| 486 | <size> | 486 | <size> |
| 487 | <width>55</width> | 487 | <width>68</width> |
| 488 | <height>16777215</height> | 488 | <height>16777215</height> |
| 489 | </size> | 489 | </size> |
| 490 | </property> | 490 | </property> |
| 491 | <property name="styleSheet"> | 491 | <property name="styleSheet"> |
| 492 | <string notr="true">min-width: 55px;</string> | 492 | <string notr="true">min-width: 68px;</string> |
| 493 | </property> | 493 | </property> |
| 494 | <property name="text"> | 494 | <property name="text"> |
| 495 | <string/> | 495 | <string/> |
| @@ -533,18 +533,18 @@ | |||
| 533 | </property> | 533 | </property> |
| 534 | <property name="minimumSize"> | 534 | <property name="minimumSize"> |
| 535 | <size> | 535 | <size> |
| 536 | <width>57</width> | 536 | <width>68</width> |
| 537 | <height>0</height> | 537 | <height>0</height> |
| 538 | </size> | 538 | </size> |
| 539 | </property> | 539 | </property> |
| 540 | <property name="maximumSize"> | 540 | <property name="maximumSize"> |
| 541 | <size> | 541 | <size> |
| 542 | <width>55</width> | 542 | <width>68</width> |
| 543 | <height>16777215</height> | 543 | <height>16777215</height> |
| 544 | </size> | 544 | </size> |
| 545 | </property> | 545 | </property> |
| 546 | <property name="styleSheet"> | 546 | <property name="styleSheet"> |
| 547 | <string notr="true">min-width: 55px;</string> | 547 | <string notr="true">min-width: 68px;</string> |
| 548 | </property> | 548 | </property> |
| 549 | <property name="text"> | 549 | <property name="text"> |
| 550 | <string/> | 550 | <string/> |
| @@ -609,18 +609,18 @@ | |||
| 609 | </property> | 609 | </property> |
| 610 | <property name="minimumSize"> | 610 | <property name="minimumSize"> |
| 611 | <size> | 611 | <size> |
| 612 | <width>57</width> | 612 | <width>68</width> |
| 613 | <height>0</height> | 613 | <height>0</height> |
| 614 | </size> | 614 | </size> |
| 615 | </property> | 615 | </property> |
| 616 | <property name="maximumSize"> | 616 | <property name="maximumSize"> |
| 617 | <size> | 617 | <size> |
| 618 | <width>55</width> | 618 | <width>68</width> |
| 619 | <height>16777215</height> | 619 | <height>16777215</height> |
| 620 | </size> | 620 | </size> |
| 621 | </property> | 621 | </property> |
| 622 | <property name="styleSheet"> | 622 | <property name="styleSheet"> |
| 623 | <string notr="true">min-width: 55px;</string> | 623 | <string notr="true">min-width: 68px;</string> |
| 624 | </property> | 624 | </property> |
| 625 | <property name="text"> | 625 | <property name="text"> |
| 626 | <string/> | 626 | <string/> |
| @@ -664,18 +664,18 @@ | |||
| 664 | </property> | 664 | </property> |
| 665 | <property name="minimumSize"> | 665 | <property name="minimumSize"> |
| 666 | <size> | 666 | <size> |
| 667 | <width>57</width> | 667 | <width>68</width> |
| 668 | <height>0</height> | 668 | <height>0</height> |
| 669 | </size> | 669 | </size> |
| 670 | </property> | 670 | </property> |
| 671 | <property name="maximumSize"> | 671 | <property name="maximumSize"> |
| 672 | <size> | 672 | <size> |
| 673 | <width>55</width> | 673 | <width>68</width> |
| 674 | <height>16777215</height> | 674 | <height>16777215</height> |
| 675 | </size> | 675 | </size> |
| 676 | </property> | 676 | </property> |
| 677 | <property name="styleSheet"> | 677 | <property name="styleSheet"> |
| 678 | <string notr="true">min-width: 55px;</string> | 678 | <string notr="true">min-width: 68px;</string> |
| 679 | </property> | 679 | </property> |
| 680 | <property name="text"> | 680 | <property name="text"> |
| 681 | <string/> | 681 | <string/> |
| @@ -782,18 +782,18 @@ | |||
| 782 | </property> | 782 | </property> |
| 783 | <property name="minimumSize"> | 783 | <property name="minimumSize"> |
| 784 | <size> | 784 | <size> |
| 785 | <width>57</width> | 785 | <width>68</width> |
| 786 | <height>0</height> | 786 | <height>0</height> |
| 787 | </size> | 787 | </size> |
| 788 | </property> | 788 | </property> |
| 789 | <property name="maximumSize"> | 789 | <property name="maximumSize"> |
| 790 | <size> | 790 | <size> |
| 791 | <width>55</width> | 791 | <width>68</width> |
| 792 | <height>16777215</height> | 792 | <height>16777215</height> |
| 793 | </size> | 793 | </size> |
| 794 | </property> | 794 | </property> |
| 795 | <property name="styleSheet"> | 795 | <property name="styleSheet"> |
| 796 | <string notr="true">min-width: 55px;</string> | 796 | <string notr="true">min-width: 68px;</string> |
| 797 | </property> | 797 | </property> |
| 798 | <property name="text"> | 798 | <property name="text"> |
| 799 | <string/> | 799 | <string/> |
| @@ -837,18 +837,18 @@ | |||
| 837 | </property> | 837 | </property> |
| 838 | <property name="minimumSize"> | 838 | <property name="minimumSize"> |
| 839 | <size> | 839 | <size> |
| 840 | <width>57</width> | 840 | <width>68</width> |
| 841 | <height>0</height> | 841 | <height>0</height> |
| 842 | </size> | 842 | </size> |
| 843 | </property> | 843 | </property> |
| 844 | <property name="maximumSize"> | 844 | <property name="maximumSize"> |
| 845 | <size> | 845 | <size> |
| 846 | <width>55</width> | 846 | <width>68</width> |
| 847 | <height>16777215</height> | 847 | <height>16777215</height> |
| 848 | </size> | 848 | </size> |
| 849 | </property> | 849 | </property> |
| 850 | <property name="styleSheet"> | 850 | <property name="styleSheet"> |
| 851 | <string notr="true">min-width: 55px;</string> | 851 | <string notr="true">min-width: 68px;</string> |
| 852 | </property> | 852 | </property> |
| 853 | <property name="text"> | 853 | <property name="text"> |
| 854 | <string/> | 854 | <string/> |
| @@ -913,18 +913,18 @@ | |||
| 913 | </property> | 913 | </property> |
| 914 | <property name="minimumSize"> | 914 | <property name="minimumSize"> |
| 915 | <size> | 915 | <size> |
| 916 | <width>57</width> | 916 | <width>68</width> |
| 917 | <height>0</height> | 917 | <height>0</height> |
| 918 | </size> | 918 | </size> |
| 919 | </property> | 919 | </property> |
| 920 | <property name="maximumSize"> | 920 | <property name="maximumSize"> |
| 921 | <size> | 921 | <size> |
| 922 | <width>55</width> | 922 | <width>68</width> |
| 923 | <height>16777215</height> | 923 | <height>16777215</height> |
| 924 | </size> | 924 | </size> |
| 925 | </property> | 925 | </property> |
| 926 | <property name="styleSheet"> | 926 | <property name="styleSheet"> |
| 927 | <string notr="true">min-width: 55px;</string> | 927 | <string notr="true">min-width: 68px;</string> |
| 928 | </property> | 928 | </property> |
| 929 | <property name="text"> | 929 | <property name="text"> |
| 930 | <string/> | 930 | <string/> |
| @@ -968,18 +968,18 @@ | |||
| 968 | </property> | 968 | </property> |
| 969 | <property name="minimumSize"> | 969 | <property name="minimumSize"> |
| 970 | <size> | 970 | <size> |
| 971 | <width>57</width> | 971 | <width>68</width> |
| 972 | <height>0</height> | 972 | <height>0</height> |
| 973 | </size> | 973 | </size> |
| 974 | </property> | 974 | </property> |
| 975 | <property name="maximumSize"> | 975 | <property name="maximumSize"> |
| 976 | <size> | 976 | <size> |
| 977 | <width>55</width> | 977 | <width>68</width> |
| 978 | <height>16777215</height> | 978 | <height>16777215</height> |
| 979 | </size> | 979 | </size> |
| 980 | </property> | 980 | </property> |
| 981 | <property name="styleSheet"> | 981 | <property name="styleSheet"> |
| 982 | <string notr="true">min-width: 55px;</string> | 982 | <string notr="true">min-width: 68px;</string> |
| 983 | </property> | 983 | </property> |
| 984 | <property name="text"> | 984 | <property name="text"> |
| 985 | <string/> | 985 | <string/> |
| @@ -1068,18 +1068,18 @@ | |||
| 1068 | </property> | 1068 | </property> |
| 1069 | <property name="minimumSize"> | 1069 | <property name="minimumSize"> |
| 1070 | <size> | 1070 | <size> |
| 1071 | <width>57</width> | 1071 | <width>68</width> |
| 1072 | <height>0</height> | 1072 | <height>0</height> |
| 1073 | </size> | 1073 | </size> |
| 1074 | </property> | 1074 | </property> |
| 1075 | <property name="maximumSize"> | 1075 | <property name="maximumSize"> |
| 1076 | <size> | 1076 | <size> |
| 1077 | <width>55</width> | 1077 | <width>68</width> |
| 1078 | <height>16777215</height> | 1078 | <height>16777215</height> |
| 1079 | </size> | 1079 | </size> |
| 1080 | </property> | 1080 | </property> |
| 1081 | <property name="styleSheet"> | 1081 | <property name="styleSheet"> |
| 1082 | <string notr="true">min-width: 55px;</string> | 1082 | <string notr="true">min-width: 68px;</string> |
| 1083 | </property> | 1083 | </property> |
| 1084 | <property name="text"> | 1084 | <property name="text"> |
| 1085 | <string/> | 1085 | <string/> |
| @@ -1123,18 +1123,18 @@ | |||
| 1123 | </property> | 1123 | </property> |
| 1124 | <property name="minimumSize"> | 1124 | <property name="minimumSize"> |
| 1125 | <size> | 1125 | <size> |
| 1126 | <width>57</width> | 1126 | <width>68</width> |
| 1127 | <height>0</height> | 1127 | <height>0</height> |
| 1128 | </size> | 1128 | </size> |
| 1129 | </property> | 1129 | </property> |
| 1130 | <property name="maximumSize"> | 1130 | <property name="maximumSize"> |
| 1131 | <size> | 1131 | <size> |
| 1132 | <width>55</width> | 1132 | <width>68</width> |
| 1133 | <height>16777215</height> | 1133 | <height>16777215</height> |
| 1134 | </size> | 1134 | </size> |
| 1135 | </property> | 1135 | </property> |
| 1136 | <property name="styleSheet"> | 1136 | <property name="styleSheet"> |
| 1137 | <string notr="true">min-width: 55px;</string> | 1137 | <string notr="true">min-width: 68px;</string> |
| 1138 | </property> | 1138 | </property> |
| 1139 | <property name="text"> | 1139 | <property name="text"> |
| 1140 | <string/> | 1140 | <string/> |
| @@ -1199,18 +1199,18 @@ | |||
| 1199 | </property> | 1199 | </property> |
| 1200 | <property name="minimumSize"> | 1200 | <property name="minimumSize"> |
| 1201 | <size> | 1201 | <size> |
| 1202 | <width>57</width> | 1202 | <width>68</width> |
| 1203 | <height>0</height> | 1203 | <height>0</height> |
| 1204 | </size> | 1204 | </size> |
| 1205 | </property> | 1205 | </property> |
| 1206 | <property name="maximumSize"> | 1206 | <property name="maximumSize"> |
| 1207 | <size> | 1207 | <size> |
| 1208 | <width>55</width> | 1208 | <width>68</width> |
| 1209 | <height>16777215</height> | 1209 | <height>16777215</height> |
| 1210 | </size> | 1210 | </size> |
| 1211 | </property> | 1211 | </property> |
| 1212 | <property name="styleSheet"> | 1212 | <property name="styleSheet"> |
| 1213 | <string notr="true">min-width: 55px;</string> | 1213 | <string notr="true">min-width: 68px;</string> |
| 1214 | </property> | 1214 | </property> |
| 1215 | <property name="text"> | 1215 | <property name="text"> |
| 1216 | <string/> | 1216 | <string/> |
| @@ -1254,18 +1254,18 @@ | |||
| 1254 | </property> | 1254 | </property> |
| 1255 | <property name="minimumSize"> | 1255 | <property name="minimumSize"> |
| 1256 | <size> | 1256 | <size> |
| 1257 | <width>57</width> | 1257 | <width>68</width> |
| 1258 | <height>0</height> | 1258 | <height>0</height> |
| 1259 | </size> | 1259 | </size> |
| 1260 | </property> | 1260 | </property> |
| 1261 | <property name="maximumSize"> | 1261 | <property name="maximumSize"> |
| 1262 | <size> | 1262 | <size> |
| 1263 | <width>55</width> | 1263 | <width>68</width> |
| 1264 | <height>16777215</height> | 1264 | <height>16777215</height> |
| 1265 | </size> | 1265 | </size> |
| 1266 | </property> | 1266 | </property> |
| 1267 | <property name="styleSheet"> | 1267 | <property name="styleSheet"> |
| 1268 | <string notr="true">min-width: 55px;</string> | 1268 | <string notr="true">min-width: 68px;</string> |
| 1269 | </property> | 1269 | </property> |
| 1270 | <property name="text"> | 1270 | <property name="text"> |
| 1271 | <string/> | 1271 | <string/> |
| @@ -1393,18 +1393,18 @@ | |||
| 1393 | </property> | 1393 | </property> |
| 1394 | <property name="minimumSize"> | 1394 | <property name="minimumSize"> |
| 1395 | <size> | 1395 | <size> |
| 1396 | <width>57</width> | 1396 | <width>68</width> |
| 1397 | <height>0</height> | 1397 | <height>0</height> |
| 1398 | </size> | 1398 | </size> |
| 1399 | </property> | 1399 | </property> |
| 1400 | <property name="maximumSize"> | 1400 | <property name="maximumSize"> |
| 1401 | <size> | 1401 | <size> |
| 1402 | <width>55</width> | 1402 | <width>68</width> |
| 1403 | <height>16777215</height> | 1403 | <height>16777215</height> |
| 1404 | </size> | 1404 | </size> |
| 1405 | </property> | 1405 | </property> |
| 1406 | <property name="styleSheet"> | 1406 | <property name="styleSheet"> |
| 1407 | <string notr="true">min-width: 55px;</string> | 1407 | <string notr="true">min-width: 68px;</string> |
| 1408 | </property> | 1408 | </property> |
| 1409 | <property name="text"> | 1409 | <property name="text"> |
| 1410 | <string/> | 1410 | <string/> |
| @@ -1448,18 +1448,18 @@ | |||
| 1448 | </property> | 1448 | </property> |
| 1449 | <property name="minimumSize"> | 1449 | <property name="minimumSize"> |
| 1450 | <size> | 1450 | <size> |
| 1451 | <width>57</width> | 1451 | <width>68</width> |
| 1452 | <height>0</height> | 1452 | <height>0</height> |
| 1453 | </size> | 1453 | </size> |
| 1454 | </property> | 1454 | </property> |
| 1455 | <property name="maximumSize"> | 1455 | <property name="maximumSize"> |
| 1456 | <size> | 1456 | <size> |
| 1457 | <width>55</width> | 1457 | <width>68</width> |
| 1458 | <height>16777215</height> | 1458 | <height>16777215</height> |
| 1459 | </size> | 1459 | </size> |
| 1460 | </property> | 1460 | </property> |
| 1461 | <property name="styleSheet"> | 1461 | <property name="styleSheet"> |
| 1462 | <string notr="true">min-width: 55px;</string> | 1462 | <string notr="true">min-width: 68px;</string> |
| 1463 | </property> | 1463 | </property> |
| 1464 | <property name="text"> | 1464 | <property name="text"> |
| 1465 | <string/> | 1465 | <string/> |
| @@ -1524,18 +1524,18 @@ | |||
| 1524 | </property> | 1524 | </property> |
| 1525 | <property name="minimumSize"> | 1525 | <property name="minimumSize"> |
| 1526 | <size> | 1526 | <size> |
| 1527 | <width>57</width> | 1527 | <width>68</width> |
| 1528 | <height>0</height> | 1528 | <height>0</height> |
| 1529 | </size> | 1529 | </size> |
| 1530 | </property> | 1530 | </property> |
| 1531 | <property name="maximumSize"> | 1531 | <property name="maximumSize"> |
| 1532 | <size> | 1532 | <size> |
| 1533 | <width>55</width> | 1533 | <width>68</width> |
| 1534 | <height>16777215</height> | 1534 | <height>16777215</height> |
| 1535 | </size> | 1535 | </size> |
| 1536 | </property> | 1536 | </property> |
| 1537 | <property name="styleSheet"> | 1537 | <property name="styleSheet"> |
| 1538 | <string notr="true">min-width: 55px;</string> | 1538 | <string notr="true">min-width: 68px;</string> |
| 1539 | </property> | 1539 | </property> |
| 1540 | <property name="text"> | 1540 | <property name="text"> |
| 1541 | <string/> | 1541 | <string/> |
| @@ -1579,18 +1579,18 @@ | |||
| 1579 | </property> | 1579 | </property> |
| 1580 | <property name="minimumSize"> | 1580 | <property name="minimumSize"> |
| 1581 | <size> | 1581 | <size> |
| 1582 | <width>57</width> | 1582 | <width>68</width> |
| 1583 | <height>0</height> | 1583 | <height>0</height> |
| 1584 | </size> | 1584 | </size> |
| 1585 | </property> | 1585 | </property> |
| 1586 | <property name="maximumSize"> | 1586 | <property name="maximumSize"> |
| 1587 | <size> | 1587 | <size> |
| 1588 | <width>55</width> | 1588 | <width>68</width> |
| 1589 | <height>16777215</height> | 1589 | <height>16777215</height> |
| 1590 | </size> | 1590 | </size> |
| 1591 | </property> | 1591 | </property> |
| 1592 | <property name="styleSheet"> | 1592 | <property name="styleSheet"> |
| 1593 | <string notr="true">min-width: 55px;</string> | 1593 | <string notr="true">min-width: 68px;</string> |
| 1594 | </property> | 1594 | </property> |
| 1595 | <property name="text"> | 1595 | <property name="text"> |
| 1596 | <string/> | 1596 | <string/> |
| @@ -1679,18 +1679,18 @@ | |||
| 1679 | </property> | 1679 | </property> |
| 1680 | <property name="minimumSize"> | 1680 | <property name="minimumSize"> |
| 1681 | <size> | 1681 | <size> |
| 1682 | <width>57</width> | 1682 | <width>68</width> |
| 1683 | <height>0</height> | 1683 | <height>0</height> |
| 1684 | </size> | 1684 | </size> |
| 1685 | </property> | 1685 | </property> |
| 1686 | <property name="maximumSize"> | 1686 | <property name="maximumSize"> |
| 1687 | <size> | 1687 | <size> |
| 1688 | <width>55</width> | 1688 | <width>68</width> |
| 1689 | <height>16777215</height> | 1689 | <height>16777215</height> |
| 1690 | </size> | 1690 | </size> |
| 1691 | </property> | 1691 | </property> |
| 1692 | <property name="styleSheet"> | 1692 | <property name="styleSheet"> |
| 1693 | <string notr="true">min-width: 55px;</string> | 1693 | <string notr="true">min-width: 68px;</string> |
| 1694 | </property> | 1694 | </property> |
| 1695 | <property name="text"> | 1695 | <property name="text"> |
| 1696 | <string/> | 1696 | <string/> |
| @@ -1734,18 +1734,18 @@ | |||
| 1734 | </property> | 1734 | </property> |
| 1735 | <property name="minimumSize"> | 1735 | <property name="minimumSize"> |
| 1736 | <size> | 1736 | <size> |
| 1737 | <width>57</width> | 1737 | <width>68</width> |
| 1738 | <height>0</height> | 1738 | <height>0</height> |
| 1739 | </size> | 1739 | </size> |
| 1740 | </property> | 1740 | </property> |
| 1741 | <property name="maximumSize"> | 1741 | <property name="maximumSize"> |
| 1742 | <size> | 1742 | <size> |
| 1743 | <width>55</width> | 1743 | <width>68</width> |
| 1744 | <height>16777215</height> | 1744 | <height>16777215</height> |
| 1745 | </size> | 1745 | </size> |
| 1746 | </property> | 1746 | </property> |
| 1747 | <property name="styleSheet"> | 1747 | <property name="styleSheet"> |
| 1748 | <string notr="true">min-width: 55px;</string> | 1748 | <string notr="true">min-width: 68px;</string> |
| 1749 | </property> | 1749 | </property> |
| 1750 | <property name="text"> | 1750 | <property name="text"> |
| 1751 | <string/> | 1751 | <string/> |
| @@ -1810,18 +1810,18 @@ | |||
| 1810 | </property> | 1810 | </property> |
| 1811 | <property name="minimumSize"> | 1811 | <property name="minimumSize"> |
| 1812 | <size> | 1812 | <size> |
| 1813 | <width>57</width> | 1813 | <width>68</width> |
| 1814 | <height>0</height> | 1814 | <height>0</height> |
| 1815 | </size> | 1815 | </size> |
| 1816 | </property> | 1816 | </property> |
| 1817 | <property name="maximumSize"> | 1817 | <property name="maximumSize"> |
| 1818 | <size> | 1818 | <size> |
| 1819 | <width>55</width> | 1819 | <width>68</width> |
| 1820 | <height>16777215</height> | 1820 | <height>16777215</height> |
| 1821 | </size> | 1821 | </size> |
| 1822 | </property> | 1822 | </property> |
| 1823 | <property name="styleSheet"> | 1823 | <property name="styleSheet"> |
| 1824 | <string notr="true">min-width: 55px;</string> | 1824 | <string notr="true">min-width: 68px;</string> |
| 1825 | </property> | 1825 | </property> |
| 1826 | <property name="text"> | 1826 | <property name="text"> |
| 1827 | <string/> | 1827 | <string/> |
| @@ -1865,18 +1865,18 @@ | |||
| 1865 | </property> | 1865 | </property> |
| 1866 | <property name="minimumSize"> | 1866 | <property name="minimumSize"> |
| 1867 | <size> | 1867 | <size> |
| 1868 | <width>57</width> | 1868 | <width>68</width> |
| 1869 | <height>0</height> | 1869 | <height>0</height> |
| 1870 | </size> | 1870 | </size> |
| 1871 | </property> | 1871 | </property> |
| 1872 | <property name="maximumSize"> | 1872 | <property name="maximumSize"> |
| 1873 | <size> | 1873 | <size> |
| 1874 | <width>55</width> | 1874 | <width>68</width> |
| 1875 | <height>16777215</height> | 1875 | <height>16777215</height> |
| 1876 | </size> | 1876 | </size> |
| 1877 | </property> | 1877 | </property> |
| 1878 | <property name="styleSheet"> | 1878 | <property name="styleSheet"> |
| 1879 | <string notr="true">min-width: 55px;</string> | 1879 | <string notr="true">min-width: 68px;</string> |
| 1880 | </property> | 1880 | </property> |
| 1881 | <property name="text"> | 1881 | <property name="text"> |
| 1882 | <string/> | 1882 | <string/> |
| @@ -1983,18 +1983,18 @@ | |||
| 1983 | </property> | 1983 | </property> |
| 1984 | <property name="minimumSize"> | 1984 | <property name="minimumSize"> |
| 1985 | <size> | 1985 | <size> |
| 1986 | <width>57</width> | 1986 | <width>68</width> |
| 1987 | <height>0</height> | 1987 | <height>0</height> |
| 1988 | </size> | 1988 | </size> |
| 1989 | </property> | 1989 | </property> |
| 1990 | <property name="maximumSize"> | 1990 | <property name="maximumSize"> |
| 1991 | <size> | 1991 | <size> |
| 1992 | <width>55</width> | 1992 | <width>68</width> |
| 1993 | <height>16777215</height> | 1993 | <height>16777215</height> |
| 1994 | </size> | 1994 | </size> |
| 1995 | </property> | 1995 | </property> |
| 1996 | <property name="styleSheet"> | 1996 | <property name="styleSheet"> |
| 1997 | <string notr="true">min-width: 55px;</string> | 1997 | <string notr="true">min-width: 68px;</string> |
| 1998 | </property> | 1998 | </property> |
| 1999 | <property name="text"> | 1999 | <property name="text"> |
| 2000 | <string/> | 2000 | <string/> |
| @@ -2038,18 +2038,18 @@ | |||
| 2038 | </property> | 2038 | </property> |
| 2039 | <property name="minimumSize"> | 2039 | <property name="minimumSize"> |
| 2040 | <size> | 2040 | <size> |
| 2041 | <width>57</width> | 2041 | <width>68</width> |
| 2042 | <height>0</height> | 2042 | <height>0</height> |
| 2043 | </size> | 2043 | </size> |
| 2044 | </property> | 2044 | </property> |
| 2045 | <property name="maximumSize"> | 2045 | <property name="maximumSize"> |
| 2046 | <size> | 2046 | <size> |
| 2047 | <width>55</width> | 2047 | <width>68</width> |
| 2048 | <height>16777215</height> | 2048 | <height>16777215</height> |
| 2049 | </size> | 2049 | </size> |
| 2050 | </property> | 2050 | </property> |
| 2051 | <property name="styleSheet"> | 2051 | <property name="styleSheet"> |
| 2052 | <string notr="true">min-width: 55px;</string> | 2052 | <string notr="true">min-width: 68px;</string> |
| 2053 | </property> | 2053 | </property> |
| 2054 | <property name="text"> | 2054 | <property name="text"> |
| 2055 | <string/> | 2055 | <string/> |
| @@ -2114,18 +2114,18 @@ | |||
| 2114 | </property> | 2114 | </property> |
| 2115 | <property name="minimumSize"> | 2115 | <property name="minimumSize"> |
| 2116 | <size> | 2116 | <size> |
| 2117 | <width>57</width> | 2117 | <width>68</width> |
| 2118 | <height>0</height> | 2118 | <height>0</height> |
| 2119 | </size> | 2119 | </size> |
| 2120 | </property> | 2120 | </property> |
| 2121 | <property name="maximumSize"> | 2121 | <property name="maximumSize"> |
| 2122 | <size> | 2122 | <size> |
| 2123 | <width>55</width> | 2123 | <width>68</width> |
| 2124 | <height>16777215</height> | 2124 | <height>16777215</height> |
| 2125 | </size> | 2125 | </size> |
| 2126 | </property> | 2126 | </property> |
| 2127 | <property name="styleSheet"> | 2127 | <property name="styleSheet"> |
| 2128 | <string notr="true">min-width: 55px;</string> | 2128 | <string notr="true">min-width: 68px;</string> |
| 2129 | </property> | 2129 | </property> |
| 2130 | <property name="text"> | 2130 | <property name="text"> |
| 2131 | <string/> | 2131 | <string/> |
| @@ -2169,18 +2169,18 @@ | |||
| 2169 | </property> | 2169 | </property> |
| 2170 | <property name="minimumSize"> | 2170 | <property name="minimumSize"> |
| 2171 | <size> | 2171 | <size> |
| 2172 | <width>57</width> | 2172 | <width>68</width> |
| 2173 | <height>0</height> | 2173 | <height>0</height> |
| 2174 | </size> | 2174 | </size> |
| 2175 | </property> | 2175 | </property> |
| 2176 | <property name="maximumSize"> | 2176 | <property name="maximumSize"> |
| 2177 | <size> | 2177 | <size> |
| 2178 | <width>55</width> | 2178 | <width>68</width> |
| 2179 | <height>16777215</height> | 2179 | <height>16777215</height> |
| 2180 | </size> | 2180 | </size> |
| 2181 | </property> | 2181 | </property> |
| 2182 | <property name="styleSheet"> | 2182 | <property name="styleSheet"> |
| 2183 | <string notr="true">min-width: 55px;</string> | 2183 | <string notr="true">min-width: 68px;</string> |
| 2184 | </property> | 2184 | </property> |
| 2185 | <property name="text"> | 2185 | <property name="text"> |
| 2186 | <string/> | 2186 | <string/> |
| @@ -2269,18 +2269,18 @@ | |||
| 2269 | </property> | 2269 | </property> |
| 2270 | <property name="minimumSize"> | 2270 | <property name="minimumSize"> |
| 2271 | <size> | 2271 | <size> |
| 2272 | <width>57</width> | 2272 | <width>68</width> |
| 2273 | <height>0</height> | 2273 | <height>0</height> |
| 2274 | </size> | 2274 | </size> |
| 2275 | </property> | 2275 | </property> |
| 2276 | <property name="maximumSize"> | 2276 | <property name="maximumSize"> |
| 2277 | <size> | 2277 | <size> |
| 2278 | <width>55</width> | 2278 | <width>68</width> |
| 2279 | <height>16777215</height> | 2279 | <height>16777215</height> |
| 2280 | </size> | 2280 | </size> |
| 2281 | </property> | 2281 | </property> |
| 2282 | <property name="styleSheet"> | 2282 | <property name="styleSheet"> |
| 2283 | <string notr="true">min-width: 55px;</string> | 2283 | <string notr="true">min-width: 68px;</string> |
| 2284 | </property> | 2284 | </property> |
| 2285 | <property name="text"> | 2285 | <property name="text"> |
| 2286 | <string/> | 2286 | <string/> |
| @@ -2324,18 +2324,18 @@ | |||
| 2324 | </property> | 2324 | </property> |
| 2325 | <property name="minimumSize"> | 2325 | <property name="minimumSize"> |
| 2326 | <size> | 2326 | <size> |
| 2327 | <width>57</width> | 2327 | <width>68</width> |
| 2328 | <height>0</height> | 2328 | <height>0</height> |
| 2329 | </size> | 2329 | </size> |
| 2330 | </property> | 2330 | </property> |
| 2331 | <property name="maximumSize"> | 2331 | <property name="maximumSize"> |
| 2332 | <size> | 2332 | <size> |
| 2333 | <width>55</width> | 2333 | <width>68</width> |
| 2334 | <height>16777215</height> | 2334 | <height>16777215</height> |
| 2335 | </size> | 2335 | </size> |
| 2336 | </property> | 2336 | </property> |
| 2337 | <property name="styleSheet"> | 2337 | <property name="styleSheet"> |
| 2338 | <string notr="true">min-width: 55px;</string> | 2338 | <string notr="true">min-width: 68px;</string> |
| 2339 | </property> | 2339 | </property> |
| 2340 | <property name="text"> | 2340 | <property name="text"> |
| 2341 | <string/> | 2341 | <string/> |
| @@ -2400,18 +2400,18 @@ | |||
| 2400 | </property> | 2400 | </property> |
| 2401 | <property name="minimumSize"> | 2401 | <property name="minimumSize"> |
| 2402 | <size> | 2402 | <size> |
| 2403 | <width>57</width> | 2403 | <width>68</width> |
| 2404 | <height>0</height> | 2404 | <height>0</height> |
| 2405 | </size> | 2405 | </size> |
| 2406 | </property> | 2406 | </property> |
| 2407 | <property name="maximumSize"> | 2407 | <property name="maximumSize"> |
| 2408 | <size> | 2408 | <size> |
| 2409 | <width>55</width> | 2409 | <width>68</width> |
| 2410 | <height>16777215</height> | 2410 | <height>16777215</height> |
| 2411 | </size> | 2411 | </size> |
| 2412 | </property> | 2412 | </property> |
| 2413 | <property name="styleSheet"> | 2413 | <property name="styleSheet"> |
| 2414 | <string notr="true">min-width: 55px;</string> | 2414 | <string notr="true">min-width: 68px;</string> |
| 2415 | </property> | 2415 | </property> |
| 2416 | <property name="text"> | 2416 | <property name="text"> |
| 2417 | <string/> | 2417 | <string/> |
| @@ -2455,18 +2455,18 @@ | |||
| 2455 | </property> | 2455 | </property> |
| 2456 | <property name="minimumSize"> | 2456 | <property name="minimumSize"> |
| 2457 | <size> | 2457 | <size> |
| 2458 | <width>57</width> | 2458 | <width>68</width> |
| 2459 | <height>0</height> | 2459 | <height>0</height> |
| 2460 | </size> | 2460 | </size> |
| 2461 | </property> | 2461 | </property> |
| 2462 | <property name="maximumSize"> | 2462 | <property name="maximumSize"> |
| 2463 | <size> | 2463 | <size> |
| 2464 | <width>55</width> | 2464 | <width>68</width> |
| 2465 | <height>16777215</height> | 2465 | <height>16777215</height> |
| 2466 | </size> | 2466 | </size> |
| 2467 | </property> | 2467 | </property> |
| 2468 | <property name="styleSheet"> | 2468 | <property name="styleSheet"> |
| 2469 | <string notr="true">min-width: 55px;</string> | 2469 | <string notr="true">min-width: 68px;</string> |
| 2470 | </property> | 2470 | </property> |
| 2471 | <property name="text"> | 2471 | <property name="text"> |
| 2472 | <string/> | 2472 | <string/> |
diff --git a/src/yuzu/configuration/configure_input_dialog.cpp b/src/yuzu/configuration/configure_input_dialog.cpp deleted file mode 100644 index 1866003c2..000000000 --- a/src/yuzu/configuration/configure_input_dialog.cpp +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_input_dialog.h" | ||
| 6 | #include "yuzu/configuration/configure_input_dialog.h" | ||
| 7 | |||
| 8 | ConfigureInputDialog::ConfigureInputDialog(QWidget* parent, std::size_t max_players, | ||
| 9 | InputCommon::InputSubsystem* input_subsystem) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputDialog>()), | ||
| 11 | input_widget(new ConfigureInput(this)) { | ||
| 12 | ui->setupUi(this); | ||
| 13 | |||
| 14 | input_widget->Initialize(input_subsystem, max_players); | ||
| 15 | |||
| 16 | ui->inputLayout->addWidget(input_widget); | ||
| 17 | |||
| 18 | RetranslateUI(); | ||
| 19 | } | ||
| 20 | |||
| 21 | ConfigureInputDialog::~ConfigureInputDialog() = default; | ||
| 22 | |||
| 23 | void ConfigureInputDialog::ApplyConfiguration() { | ||
| 24 | input_widget->ApplyConfiguration(); | ||
| 25 | } | ||
| 26 | |||
| 27 | void ConfigureInputDialog::changeEvent(QEvent* event) { | ||
| 28 | if (event->type() == QEvent::LanguageChange) { | ||
| 29 | RetranslateUI(); | ||
| 30 | } | ||
| 31 | |||
| 32 | QDialog::changeEvent(event); | ||
| 33 | } | ||
| 34 | |||
| 35 | void ConfigureInputDialog::RetranslateUI() { | ||
| 36 | ui->retranslateUi(this); | ||
| 37 | } | ||
diff --git a/src/yuzu/configuration/configure_input_dialog.h b/src/yuzu/configuration/configure_input_dialog.h deleted file mode 100644 index d1bd865f9..000000000 --- a/src/yuzu/configuration/configure_input_dialog.h +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | #include "yuzu/configuration/configure_input.h" | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | |||
| 13 | namespace InputCommon { | ||
| 14 | class InputSubsystem; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | ||
| 18 | class ConfigureInputDialog; | ||
| 19 | } | ||
| 20 | |||
| 21 | class ConfigureInputDialog : public QDialog { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureInputDialog(QWidget* parent, std::size_t max_players, | ||
| 26 | InputCommon::InputSubsystem* input_subsystem); | ||
| 27 | ~ConfigureInputDialog() override; | ||
| 28 | |||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | void changeEvent(QEvent* event) override; | ||
| 33 | void RetranslateUI(); | ||
| 34 | |||
| 35 | std::unique_ptr<Ui::ConfigureInputDialog> ui; | ||
| 36 | |||
| 37 | ConfigureInput* input_widget; | ||
| 38 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index f58ca29d7..56ab32a35 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <thread> | ||
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include <QGridLayout> | 9 | #include <QGridLayout> |
| 9 | #include <QInputDialog> | 10 | #include <QInputDialog> |
| @@ -22,8 +23,9 @@ | |||
| 22 | #include "ui_configure_input_player.h" | 23 | #include "ui_configure_input_player.h" |
| 23 | #include "yuzu/configuration/config.h" | 24 | #include "yuzu/configuration/config.h" |
| 24 | #include "yuzu/configuration/configure_input_player.h" | 25 | #include "yuzu/configuration/configure_input_player.h" |
| 25 | 26 | #include "yuzu/configuration/configure_vibration.h" | |
| 26 | constexpr std::size_t HANDHELD_INDEX = 8; | 27 | #include "yuzu/configuration/input_profiles.h" |
| 28 | #include "yuzu/util/limitable_input_dialog.h" | ||
| 27 | 29 | ||
| 28 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | 30 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> |
| 29 | ConfigureInputPlayer::analog_sub_buttons{{ | 31 | ConfigureInputPlayer::analog_sub_buttons{{ |
| @@ -35,6 +37,8 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | |||
| 35 | 37 | ||
| 36 | namespace { | 38 | namespace { |
| 37 | 39 | ||
| 40 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 41 | |||
| 38 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, | 42 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, |
| 39 | bool connected) { | 43 | bool connected) { |
| 40 | Core::System& system{Core::System::GetInstance()}; | 44 | Core::System& system{Core::System::GetInstance()}; |
| @@ -240,10 +244,11 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) | |||
| 240 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, | 244 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, |
| 241 | QWidget* bottom_row, | 245 | QWidget* bottom_row, |
| 242 | InputCommon::InputSubsystem* input_subsystem_, | 246 | InputCommon::InputSubsystem* input_subsystem_, |
| 243 | bool debug) | 247 | InputProfiles* profiles_, bool debug) |
| 244 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | 248 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), |
| 245 | debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()), | 249 | debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_), |
| 246 | poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { | 250 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()), |
| 251 | bottom_row(bottom_row) { | ||
| 247 | ui->setupUi(this); | 252 | ui->setupUi(this); |
| 248 | 253 | ||
| 249 | setFocusPolicy(Qt::ClickFocus); | 254 | setFocusPolicy(Qt::ClickFocus); |
| @@ -366,6 +371,18 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 366 | } | 371 | } |
| 367 | 372 | ||
| 368 | connect(analog_button, &QPushButton::clicked, [=, this] { | 373 | connect(analog_button, &QPushButton::clicked, [=, this] { |
| 374 | if (!map_analog_stick_accepted) { | ||
| 375 | map_analog_stick_accepted = | ||
| 376 | QMessageBox::information( | ||
| 377 | this, tr("Map Analog Stick"), | ||
| 378 | tr("After pressing OK, first move your joystick horizontally, and then " | ||
| 379 | "vertically.\nTo invert the axes, first move your joystick " | ||
| 380 | "vertically, and then horizontally."), | ||
| 381 | QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok; | ||
| 382 | if (!map_analog_stick_accepted) { | ||
| 383 | return; | ||
| 384 | } | ||
| 385 | } | ||
| 369 | HandleClick( | 386 | HandleClick( |
| 370 | analog_map_buttons[analog_id][sub_button_id], | 387 | analog_map_buttons[analog_id][sub_button_id], |
| 371 | [=, this](const Common::ParamPackage& params) { | 388 | [=, this](const Common::ParamPackage& params) { |
| @@ -455,11 +472,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 455 | }); | 472 | }); |
| 456 | } | 473 | } |
| 457 | 474 | ||
| 475 | if (debug || player_index == 9) { | ||
| 476 | ui->groupConnectedController->setCheckable(false); | ||
| 477 | } | ||
| 478 | |||
| 458 | // The Debug Controller can only choose the Pro Controller. | 479 | // The Debug Controller can only choose the Pro Controller. |
| 459 | if (debug) { | 480 | if (debug) { |
| 460 | ui->buttonScreenshot->setEnabled(false); | 481 | ui->buttonScreenshot->setEnabled(false); |
| 461 | ui->buttonHome->setEnabled(false); | 482 | ui->buttonHome->setEnabled(false); |
| 462 | ui->groupConnectedController->setCheckable(false); | ||
| 463 | QStringList debug_controller_types = { | 483 | QStringList debug_controller_types = { |
| 464 | tr("Pro Controller"), | 484 | tr("Pro Controller"), |
| 465 | }; | 485 | }; |
| @@ -477,11 +497,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 477 | UpdateMotionButtons(); | 497 | UpdateMotionButtons(); |
| 478 | }); | 498 | }); |
| 479 | 499 | ||
| 480 | connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, | 500 | connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, |
| 481 | &ConfigureInputPlayer::UpdateMappingWithDefaults); | 501 | &ConfigureInputPlayer::UpdateMappingWithDefaults); |
| 482 | 502 | ||
| 503 | ui->comboDevices->setCurrentIndex(-1); | ||
| 504 | |||
| 483 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | 505 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); |
| 484 | UpdateInputDevices(); | ||
| 485 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, | 506 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, |
| 486 | [this] { emit RefreshInputDevices(); }); | 507 | [this] { emit RefreshInputDevices(); }); |
| 487 | 508 | ||
| @@ -492,14 +513,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 492 | Common::ParamPackage params; | 513 | Common::ParamPackage params; |
| 493 | if (input_subsystem->GetGCButtons()->IsPolling()) { | 514 | if (input_subsystem->GetGCButtons()->IsPolling()) { |
| 494 | params = input_subsystem->GetGCButtons()->GetNextInput(); | 515 | params = input_subsystem->GetGCButtons()->GetNextInput(); |
| 495 | if (params.Has("engine")) { | 516 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 496 | SetPollingResult(params, false); | 517 | SetPollingResult(params, false); |
| 497 | return; | 518 | return; |
| 498 | } | 519 | } |
| 499 | } | 520 | } |
| 500 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { | 521 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { |
| 501 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); | 522 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); |
| 502 | if (params.Has("engine")) { | 523 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 503 | SetPollingResult(params, false); | 524 | SetPollingResult(params, false); |
| 504 | return; | 525 | return; |
| 505 | } | 526 | } |
| @@ -513,13 +534,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 513 | } | 534 | } |
| 514 | for (auto& poller : device_pollers) { | 535 | for (auto& poller : device_pollers) { |
| 515 | params = poller->GetNextInput(); | 536 | params = poller->GetNextInput(); |
| 516 | if (params.Has("engine")) { | 537 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 517 | SetPollingResult(params, false); | 538 | SetPollingResult(params, false); |
| 518 | return; | 539 | return; |
| 519 | } | 540 | } |
| 520 | } | 541 | } |
| 521 | }); | 542 | }); |
| 522 | 543 | ||
| 544 | UpdateInputProfiles(); | ||
| 545 | |||
| 546 | connect(ui->buttonProfilesNew, &QPushButton::clicked, this, | ||
| 547 | &ConfigureInputPlayer::CreateProfile); | ||
| 548 | connect(ui->buttonProfilesDelete, &QPushButton::clicked, this, | ||
| 549 | &ConfigureInputPlayer::DeleteProfile); | ||
| 550 | connect(ui->comboProfiles, qOverload<int>(&QComboBox::activated), this, | ||
| 551 | &ConfigureInputPlayer::LoadProfile); | ||
| 552 | connect(ui->buttonProfilesSave, &QPushButton::clicked, this, | ||
| 553 | &ConfigureInputPlayer::SaveProfile); | ||
| 554 | |||
| 523 | LoadConfiguration(); | 555 | LoadConfiguration(); |
| 524 | 556 | ||
| 525 | // TODO(wwylele): enable this when we actually emulate it | 557 | // TODO(wwylele): enable this when we actually emulate it |
| @@ -529,7 +561,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 529 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; | 561 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; |
| 530 | 562 | ||
| 531 | void ConfigureInputPlayer::ApplyConfiguration() { | 563 | void ConfigureInputPlayer::ApplyConfiguration() { |
| 532 | auto& player = Settings::values.players[player_index]; | 564 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 533 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; | 565 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; |
| 534 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; | 566 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; |
| 535 | 567 | ||
| @@ -543,33 +575,58 @@ void ConfigureInputPlayer::ApplyConfiguration() { | |||
| 543 | } | 575 | } |
| 544 | 576 | ||
| 545 | auto& motions = player.motions; | 577 | auto& motions = player.motions; |
| 578 | |||
| 546 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), | 579 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), |
| 547 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 580 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 548 | 581 | ||
| 549 | player.controller_type = | 582 | const auto controller_type = |
| 550 | static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex()); | 583 | GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); |
| 551 | player.connected = ui->groupConnectedController->isChecked(); | 584 | const auto player_connected = ui->groupConnectedController->isChecked() && |
| 585 | controller_type != Settings::ControllerType::Handheld; | ||
| 552 | 586 | ||
| 553 | // Player 2-8 | 587 | if (player.controller_type == controller_type && player.connected == player_connected) { |
| 554 | if (player_index != 0) { | 588 | // Set vibration devices in the event that the input device has changed. |
| 555 | UpdateController(player.controller_type, player_index, player.connected); | 589 | ConfigureVibration::SetVibrationDevices(player_index); |
| 556 | return; | 590 | return; |
| 557 | } | 591 | } |
| 558 | 592 | ||
| 559 | // Player 1 and Handheld | 593 | // Disconnect the controller first. |
| 560 | auto& handheld = Settings::values.players[HANDHELD_INDEX]; | 594 | UpdateController(controller_type, player_index, false); |
| 561 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. | 595 | |
| 562 | if (player.controller_type == Settings::ControllerType::Handheld) { | 596 | player.controller_type = controller_type; |
| 563 | handheld = player; | 597 | player.connected = player_connected; |
| 564 | handheld.connected = ui->groupConnectedController->isChecked(); | 598 | |
| 565 | player.connected = false; // Disconnect Player 1 | 599 | ConfigureVibration::SetVibrationDevices(player_index); |
| 566 | } else { | 600 | |
| 567 | player.connected = ui->groupConnectedController->isChecked(); | 601 | // Handheld |
| 568 | handheld.connected = false; // Disconnect Handheld | 602 | if (player_index == 0) { |
| 603 | auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 604 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 605 | handheld = player; | ||
| 606 | } | ||
| 607 | handheld.connected = ui->groupConnectedController->isChecked() && | ||
| 608 | controller_type == Settings::ControllerType::Handheld; | ||
| 609 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | ||
| 610 | } | ||
| 611 | |||
| 612 | if (!player.connected) { | ||
| 613 | return; | ||
| 569 | } | 614 | } |
| 570 | 615 | ||
| 571 | UpdateController(player.controller_type, player_index, player.connected); | 616 | // This emulates a delay between disconnecting and reconnecting controllers as some games |
| 572 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | 617 | // do not respond to a change in controller type if it was instantaneous. |
| 618 | using namespace std::chrono_literals; | ||
| 619 | std::this_thread::sleep_for(20ms); | ||
| 620 | |||
| 621 | UpdateController(controller_type, player_index, player_connected); | ||
| 622 | } | ||
| 623 | |||
| 624 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | ||
| 625 | if (bottom_row == nullptr) { | ||
| 626 | return; | ||
| 627 | } | ||
| 628 | QWidget::showEvent(event); | ||
| 629 | ui->main->addWidget(bottom_row); | ||
| 573 | } | 630 | } |
| 574 | 631 | ||
| 575 | void ConfigureInputPlayer::changeEvent(QEvent* event) { | 632 | void ConfigureInputPlayer::changeEvent(QEvent* event) { |
| @@ -586,7 +643,7 @@ void ConfigureInputPlayer::RetranslateUI() { | |||
| 586 | } | 643 | } |
| 587 | 644 | ||
| 588 | void ConfigureInputPlayer::LoadConfiguration() { | 645 | void ConfigureInputPlayer::LoadConfiguration() { |
| 589 | auto& player = Settings::values.players[player_index]; | 646 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 590 | if (debug) { | 647 | if (debug) { |
| 591 | std::transform(Settings::values.debug_pad_buttons.begin(), | 648 | std::transform(Settings::values.debug_pad_buttons.begin(), |
| 592 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), | 649 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), |
| @@ -604,6 +661,7 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 604 | } | 661 | } |
| 605 | 662 | ||
| 606 | UpdateUI(); | 663 | UpdateUI(); |
| 664 | UpdateInputDeviceCombobox(); | ||
| 607 | 665 | ||
| 608 | if (debug) { | 666 | if (debug) { |
| 609 | return; | 667 | return; |
| @@ -612,44 +670,75 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 612 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); | 670 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); |
| 613 | ui->groupConnectedController->setChecked( | 671 | ui->groupConnectedController->setChecked( |
| 614 | player.connected || | 672 | player.connected || |
| 615 | (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); | 673 | (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected)); |
| 616 | } | 674 | } |
| 617 | 675 | ||
| 618 | void ConfigureInputPlayer::UpdateInputDevices() { | 676 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { |
| 619 | input_devices = input_subsystem->GetInputDevices(); | 677 | ui->groupConnectedController->setChecked(connected); |
| 620 | ui->comboDevices->clear(); | ||
| 621 | for (auto device : input_devices) { | ||
| 622 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 623 | } | ||
| 624 | } | 678 | } |
| 625 | 679 | ||
| 626 | void ConfigureInputPlayer::RestoreDefaults() { | 680 | void ConfigureInputPlayer::UpdateInputDeviceCombobox() { |
| 627 | // Reset Buttons | 681 | // Skip input device persistence if "Input Devices" is set to "Any". |
| 628 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 682 | if (ui->comboDevices->currentIndex() == 0) { |
| 629 | buttons_param[button_id] = Common::ParamPackage{ | 683 | UpdateInputDevices(); |
| 630 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | 684 | return; |
| 631 | } | 685 | } |
| 632 | 686 | ||
| 633 | // Reset Analogs and Modifier Buttons | 687 | // Find the first button that isn't empty. |
| 634 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | 688 | const auto button_param = |
| 635 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | 689 | std::find_if(buttons_param.begin(), buttons_param.end(), |
| 636 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 690 | [](const Common::ParamPackage param) { return param.Has("engine"); }); |
| 637 | Config::default_analogs[analog_id][sub_button_id])}; | 691 | const bool buttons_empty = button_param == buttons_param.end(); |
| 638 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | ||
| 639 | } | ||
| 640 | 692 | ||
| 641 | analogs_param[analog_id].Set( | 693 | const auto current_engine = button_param->Get("engine", ""); |
| 642 | "modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id])); | 694 | const auto current_guid = button_param->Get("guid", ""); |
| 695 | const auto current_port = button_param->Get("port", ""); | ||
| 696 | |||
| 697 | const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse"; | ||
| 698 | |||
| 699 | UpdateInputDevices(); | ||
| 700 | |||
| 701 | if (buttons_empty) { | ||
| 702 | return; | ||
| 643 | } | 703 | } |
| 644 | 704 | ||
| 645 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 705 | const bool all_one_device = |
| 646 | motions_param[motion_id] = Common::ParamPackage{ | 706 | std::all_of(buttons_param.begin(), buttons_param.end(), |
| 647 | InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; | 707 | [current_engine, current_guid, current_port, |
| 708 | is_keyboard_mouse](const Common::ParamPackage param) { | ||
| 709 | if (is_keyboard_mouse) { | ||
| 710 | return !param.Has("engine") || param.Get("engine", "") == "keyboard" || | ||
| 711 | param.Get("engine", "") == "mouse"; | ||
| 712 | } | ||
| 713 | return !param.Has("engine") || (param.Get("engine", "") == current_engine && | ||
| 714 | param.Get("guid", "") == current_guid && | ||
| 715 | param.Get("port", "") == current_port); | ||
| 716 | }); | ||
| 717 | |||
| 718 | if (all_one_device) { | ||
| 719 | if (is_keyboard_mouse) { | ||
| 720 | ui->comboDevices->setCurrentIndex(1); | ||
| 721 | return; | ||
| 722 | } | ||
| 723 | const auto devices_it = std::find_if( | ||
| 724 | input_devices.begin(), input_devices.end(), | ||
| 725 | [current_engine, current_guid, current_port](const Common::ParamPackage param) { | ||
| 726 | return param.Get("class", "") == current_engine && | ||
| 727 | param.Get("guid", "") == current_guid && | ||
| 728 | param.Get("port", "") == current_port; | ||
| 729 | }); | ||
| 730 | const int device_index = | ||
| 731 | devices_it != input_devices.end() | ||
| 732 | ? static_cast<int>(std::distance(input_devices.begin(), devices_it)) | ||
| 733 | : 0; | ||
| 734 | ui->comboDevices->setCurrentIndex(device_index); | ||
| 735 | } else { | ||
| 736 | ui->comboDevices->setCurrentIndex(0); | ||
| 648 | } | 737 | } |
| 738 | } | ||
| 649 | 739 | ||
| 650 | UpdateUI(); | 740 | void ConfigureInputPlayer::RestoreDefaults() { |
| 651 | UpdateInputDevices(); | 741 | UpdateMappingWithDefaults(); |
| 652 | ui->comboControllerType->setCurrentIndex(0); | ||
| 653 | } | 742 | } |
| 654 | 743 | ||
| 655 | void ConfigureInputPlayer::ClearAll() { | 744 | void ConfigureInputPlayer::ClearAll() { |
| @@ -752,10 +841,167 @@ void ConfigureInputPlayer::UpdateUI() { | |||
| 752 | } | 841 | } |
| 753 | } | 842 | } |
| 754 | 843 | ||
| 844 | void ConfigureInputPlayer::UpdateInputDevices() { | ||
| 845 | input_devices = input_subsystem->GetInputDevices(); | ||
| 846 | ui->comboDevices->clear(); | ||
| 847 | for (auto device : input_devices) { | ||
| 848 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 849 | } | ||
| 850 | } | ||
| 851 | |||
| 852 | void ConfigureInputPlayer::UpdateControllerIcon() { | ||
| 853 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | ||
| 854 | // "nonstandard" to use an image through the icon support) | ||
| 855 | const QString stylesheet = [this] { | ||
| 856 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 857 | case Settings::ControllerType::ProController: | ||
| 858 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 859 | case Settings::ControllerType::DualJoyconDetached: | ||
| 860 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 861 | case Settings::ControllerType::LeftJoycon: | ||
| 862 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 863 | case Settings::ControllerType::RightJoycon: | ||
| 864 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 865 | case Settings::ControllerType::Handheld: | ||
| 866 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 867 | default: | ||
| 868 | return QString{}; | ||
| 869 | } | ||
| 870 | }(); | ||
| 871 | |||
| 872 | const QString theme = [] { | ||
| 873 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 874 | return QStringLiteral("_dark"); | ||
| 875 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 876 | return QStringLiteral("_midnight"); | ||
| 877 | } else { | ||
| 878 | return QString{}; | ||
| 879 | } | ||
| 880 | }(); | ||
| 881 | |||
| 882 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | ||
| 883 | } | ||
| 884 | |||
| 885 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | ||
| 886 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | ||
| 887 | if (debug) { | ||
| 888 | layout = Settings::ControllerType::ProController; | ||
| 889 | } | ||
| 890 | |||
| 891 | // List of all the widgets that will be hidden by any of the following layouts that need | ||
| 892 | // "unhidden" after the controller type changes | ||
| 893 | const std::array<QWidget*, 9> layout_show = { | ||
| 894 | ui->buttonShoulderButtonsSLSR, | ||
| 895 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 896 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 897 | ui->buttonShoulderButtonsLeft, | ||
| 898 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 899 | ui->bottomLeft, | ||
| 900 | ui->buttonShoulderButtonsRight, | ||
| 901 | ui->buttonMiscButtonsPlusHome, | ||
| 902 | ui->bottomRight, | ||
| 903 | }; | ||
| 904 | |||
| 905 | for (auto* widget : layout_show) { | ||
| 906 | widget->show(); | ||
| 907 | } | ||
| 908 | |||
| 909 | std::vector<QWidget*> layout_hidden; | ||
| 910 | switch (layout) { | ||
| 911 | case Settings::ControllerType::ProController: | ||
| 912 | case Settings::ControllerType::DualJoyconDetached: | ||
| 913 | case Settings::ControllerType::Handheld: | ||
| 914 | layout_hidden = { | ||
| 915 | ui->buttonShoulderButtonsSLSR, | ||
| 916 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 917 | }; | ||
| 918 | break; | ||
| 919 | case Settings::ControllerType::LeftJoycon: | ||
| 920 | layout_hidden = { | ||
| 921 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 922 | ui->buttonShoulderButtonsRight, | ||
| 923 | ui->buttonMiscButtonsPlusHome, | ||
| 924 | ui->bottomRight, | ||
| 925 | }; | ||
| 926 | break; | ||
| 927 | case Settings::ControllerType::RightJoycon: | ||
| 928 | layout_hidden = { | ||
| 929 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 930 | ui->buttonShoulderButtonsLeft, | ||
| 931 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 932 | ui->bottomLeft, | ||
| 933 | }; | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | |||
| 937 | for (auto* widget : layout_hidden) { | ||
| 938 | widget->hide(); | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | void ConfigureInputPlayer::UpdateMotionButtons() { | ||
| 943 | if (debug) { | ||
| 944 | // Motion isn't used with the debug controller, hide both groupboxes. | ||
| 945 | ui->buttonMotionLeftGroup->hide(); | ||
| 946 | ui->buttonMotionRightGroup->hide(); | ||
| 947 | return; | ||
| 948 | } | ||
| 949 | |||
| 950 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. | ||
| 951 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 952 | case Settings::ControllerType::ProController: | ||
| 953 | case Settings::ControllerType::LeftJoycon: | ||
| 954 | case Settings::ControllerType::Handheld: | ||
| 955 | // Show "Motion 1" and hide "Motion 2". | ||
| 956 | ui->buttonMotionLeftGroup->show(); | ||
| 957 | ui->buttonMotionRightGroup->hide(); | ||
| 958 | break; | ||
| 959 | case Settings::ControllerType::RightJoycon: | ||
| 960 | // Show "Motion 2" and hide "Motion 1". | ||
| 961 | ui->buttonMotionLeftGroup->hide(); | ||
| 962 | ui->buttonMotionRightGroup->show(); | ||
| 963 | break; | ||
| 964 | case Settings::ControllerType::DualJoyconDetached: | ||
| 965 | default: | ||
| 966 | // Show both "Motion 1/2". | ||
| 967 | ui->buttonMotionLeftGroup->show(); | ||
| 968 | ui->buttonMotionRightGroup->show(); | ||
| 969 | break; | ||
| 970 | } | ||
| 971 | } | ||
| 972 | |||
| 755 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { | 973 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { |
| 756 | if (ui->comboDevices->currentIndex() < 2) { | 974 | if (ui->comboDevices->currentIndex() == 0) { |
| 757 | return; | 975 | return; |
| 758 | } | 976 | } |
| 977 | |||
| 978 | if (ui->comboDevices->currentIndex() == 1) { | ||
| 979 | // Reset keyboard bindings | ||
| 980 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | ||
| 981 | buttons_param[button_id] = Common::ParamPackage{ | ||
| 982 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | ||
| 983 | } | ||
| 984 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 985 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 986 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | ||
| 987 | Config::default_analogs[analog_id][sub_button_id])}; | ||
| 988 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | ||
| 989 | } | ||
| 990 | |||
| 991 | analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam( | ||
| 992 | Config::default_stick_mod[analog_id])); | ||
| 993 | } | ||
| 994 | |||
| 995 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | ||
| 996 | motions_param[motion_id] = Common::ParamPackage{ | ||
| 997 | InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; | ||
| 998 | } | ||
| 999 | |||
| 1000 | UpdateUI(); | ||
| 1001 | return; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | // Reset controller bindings | ||
| 759 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 1005 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; |
| 760 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 1006 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); |
| 761 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 1007 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); |
| @@ -828,9 +1074,27 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, | |||
| 828 | } | 1074 | } |
| 829 | 1075 | ||
| 830 | UpdateUI(); | 1076 | UpdateUI(); |
| 1077 | UpdateInputDeviceCombobox(); | ||
| 1078 | |||
| 831 | input_setter = std::nullopt; | 1079 | input_setter = std::nullopt; |
| 832 | } | 1080 | } |
| 833 | 1081 | ||
| 1082 | bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) const { | ||
| 1083 | if (ui->comboDevices->currentIndex() == 0) { | ||
| 1084 | return true; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | // Keyboard/Mouse | ||
| 1088 | if (ui->comboDevices->currentIndex() == 1) { | ||
| 1089 | return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse"; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; | ||
| 1093 | return params.Get("engine", "") == current_input_device.Get("class", "") && | ||
| 1094 | params.Get("guid", "") == current_input_device.Get("guid", "") && | ||
| 1095 | params.Get("port", "") == current_input_device.Get("port", ""); | ||
| 1096 | } | ||
| 1097 | |||
| 834 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { | 1098 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { |
| 835 | if (!input_setter || !event) { | 1099 | if (!input_setter || !event) { |
| 836 | return; | 1100 | return; |
| @@ -865,135 +1129,101 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | |||
| 865 | SetPollingResult({}, true); | 1129 | SetPollingResult({}, true); |
| 866 | } | 1130 | } |
| 867 | 1131 | ||
| 868 | void ConfigureInputPlayer::UpdateControllerIcon() { | 1132 | void ConfigureInputPlayer::CreateProfile() { |
| 869 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | 1133 | const auto profile_name = |
| 870 | // "nonstandard" to use an image through the icon support) | 1134 | LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20); |
| 871 | const QString stylesheet = [this] { | ||
| 872 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 873 | case Settings::ControllerType::ProController: | ||
| 874 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 875 | case Settings::ControllerType::DualJoyconDetached: | ||
| 876 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 877 | case Settings::ControllerType::LeftJoycon: | ||
| 878 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 879 | case Settings::ControllerType::RightJoycon: | ||
| 880 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 881 | case Settings::ControllerType::Handheld: | ||
| 882 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 883 | default: | ||
| 884 | return QString{}; | ||
| 885 | } | ||
| 886 | }(); | ||
| 887 | |||
| 888 | const QString theme = [this] { | ||
| 889 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 890 | return QStringLiteral("_dark"); | ||
| 891 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 892 | return QStringLiteral("_midnight"); | ||
| 893 | } else { | ||
| 894 | return QString{}; | ||
| 895 | } | ||
| 896 | }(); | ||
| 897 | 1135 | ||
| 898 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | 1136 | if (profile_name.isEmpty()) { |
| 899 | } | 1137 | return; |
| 1138 | } | ||
| 900 | 1139 | ||
| 901 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | 1140 | if (!InputProfiles::IsProfileNameValid(profile_name.toStdString())) { |
| 902 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 1141 | QMessageBox::critical(this, tr("Create Input Profile"), |
| 903 | if (debug) { | 1142 | tr("The given profile name is not valid!")); |
| 904 | layout = Settings::ControllerType::ProController; | 1143 | return; |
| 905 | } | 1144 | } |
| 906 | 1145 | ||
| 907 | // List of all the widgets that will be hidden by any of the following layouts that need | 1146 | ApplyConfiguration(); |
| 908 | // "unhidden" after the controller type changes | ||
| 909 | const std::array<QWidget*, 9> layout_show = { | ||
| 910 | ui->buttonShoulderButtonsSLSR, | ||
| 911 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 912 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 913 | ui->buttonShoulderButtonsLeft, | ||
| 914 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 915 | ui->bottomLeft, | ||
| 916 | ui->buttonShoulderButtonsRight, | ||
| 917 | ui->buttonMiscButtonsPlusHome, | ||
| 918 | ui->bottomRight, | ||
| 919 | }; | ||
| 920 | 1147 | ||
| 921 | for (auto* widget : layout_show) { | 1148 | if (!profiles->CreateProfile(profile_name.toStdString(), player_index)) { |
| 922 | widget->show(); | 1149 | QMessageBox::critical(this, tr("Create Input Profile"), |
| 1150 | tr("Failed to create the input profile \"%1\"").arg(profile_name)); | ||
| 1151 | UpdateInputProfiles(); | ||
| 1152 | emit RefreshInputProfiles(player_index); | ||
| 1153 | return; | ||
| 923 | } | 1154 | } |
| 924 | 1155 | ||
| 925 | std::vector<QWidget*> layout_hidden; | 1156 | emit RefreshInputProfiles(player_index); |
| 926 | switch (layout) { | 1157 | |
| 927 | case Settings::ControllerType::ProController: | 1158 | ui->comboProfiles->addItem(profile_name); |
| 928 | case Settings::ControllerType::DualJoyconDetached: | 1159 | ui->comboProfiles->setCurrentIndex(ui->comboProfiles->count() - 1); |
| 929 | case Settings::ControllerType::Handheld: | 1160 | } |
| 930 | layout_hidden = { | 1161 | |
| 931 | ui->buttonShoulderButtonsSLSR, | 1162 | void ConfigureInputPlayer::DeleteProfile() { |
| 932 | ui->horizontalSpacerShoulderButtonsWidget2, | 1163 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 933 | }; | 1164 | |
| 934 | break; | 1165 | if (profile_name.isEmpty()) { |
| 935 | case Settings::ControllerType::LeftJoycon: | 1166 | return; |
| 936 | layout_hidden = { | ||
| 937 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 938 | ui->buttonShoulderButtonsRight, | ||
| 939 | ui->buttonMiscButtonsPlusHome, | ||
| 940 | ui->bottomRight, | ||
| 941 | }; | ||
| 942 | break; | ||
| 943 | case Settings::ControllerType::RightJoycon: | ||
| 944 | layout_hidden = { | ||
| 945 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 946 | ui->buttonShoulderButtonsLeft, | ||
| 947 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 948 | ui->bottomLeft, | ||
| 949 | }; | ||
| 950 | break; | ||
| 951 | } | 1167 | } |
| 952 | 1168 | ||
| 953 | for (auto* widget : layout_hidden) { | 1169 | if (!profiles->DeleteProfile(profile_name.toStdString())) { |
| 954 | widget->hide(); | 1170 | QMessageBox::critical(this, tr("Delete Input Profile"), |
| 1171 | tr("Failed to delete the input profile \"%1\"").arg(profile_name)); | ||
| 1172 | UpdateInputProfiles(); | ||
| 1173 | emit RefreshInputProfiles(player_index); | ||
| 1174 | return; | ||
| 955 | } | 1175 | } |
| 1176 | |||
| 1177 | emit RefreshInputProfiles(player_index); | ||
| 1178 | |||
| 1179 | ui->comboProfiles->removeItem(ui->comboProfiles->currentIndex()); | ||
| 1180 | ui->comboProfiles->setCurrentIndex(-1); | ||
| 956 | } | 1181 | } |
| 957 | 1182 | ||
| 958 | void ConfigureInputPlayer::UpdateMotionButtons() { | 1183 | void ConfigureInputPlayer::LoadProfile() { |
| 959 | if (debug) { | 1184 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 960 | // Motion isn't used with the debug controller, hide both groupboxes. | 1185 | |
| 961 | ui->buttonMotionLeftGroup->hide(); | 1186 | if (profile_name.isEmpty()) { |
| 962 | ui->buttonMotionRightGroup->hide(); | ||
| 963 | return; | 1187 | return; |
| 964 | } | 1188 | } |
| 965 | 1189 | ||
| 966 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. | 1190 | ApplyConfiguration(); |
| 967 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | 1191 | |
| 968 | case Settings::ControllerType::ProController: | 1192 | if (!profiles->LoadProfile(profile_name.toStdString(), player_index)) { |
| 969 | case Settings::ControllerType::LeftJoycon: | 1193 | QMessageBox::critical(this, tr("Load Input Profile"), |
| 970 | case Settings::ControllerType::Handheld: | 1194 | tr("Failed to load the input profile \"%1\"").arg(profile_name)); |
| 971 | // Show "Motion 1" and hide "Motion 2". | 1195 | UpdateInputProfiles(); |
| 972 | ui->buttonMotionLeftGroup->show(); | 1196 | emit RefreshInputProfiles(player_index); |
| 973 | ui->buttonMotionRightGroup->hide(); | 1197 | return; |
| 974 | break; | ||
| 975 | case Settings::ControllerType::RightJoycon: | ||
| 976 | // Show "Motion 2" and hide "Motion 1". | ||
| 977 | ui->buttonMotionLeftGroup->hide(); | ||
| 978 | ui->buttonMotionRightGroup->show(); | ||
| 979 | break; | ||
| 980 | case Settings::ControllerType::DualJoyconDetached: | ||
| 981 | default: | ||
| 982 | // Show both "Motion 1/2". | ||
| 983 | ui->buttonMotionLeftGroup->show(); | ||
| 984 | ui->buttonMotionRightGroup->show(); | ||
| 985 | break; | ||
| 986 | } | 1198 | } |
| 1199 | |||
| 1200 | LoadConfiguration(); | ||
| 987 | } | 1201 | } |
| 988 | 1202 | ||
| 989 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | 1203 | void ConfigureInputPlayer::SaveProfile() { |
| 990 | if (bottom_row == nullptr) { | 1204 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 1205 | |||
| 1206 | if (profile_name.isEmpty()) { | ||
| 1207 | return; | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | ApplyConfiguration(); | ||
| 1211 | |||
| 1212 | if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) { | ||
| 1213 | QMessageBox::critical(this, tr("Save Input Profile"), | ||
| 1214 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); | ||
| 1215 | UpdateInputProfiles(); | ||
| 1216 | emit RefreshInputProfiles(player_index); | ||
| 991 | return; | 1217 | return; |
| 992 | } | 1218 | } |
| 993 | QWidget::showEvent(event); | ||
| 994 | ui->main->addWidget(bottom_row); | ||
| 995 | } | 1219 | } |
| 996 | 1220 | ||
| 997 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { | 1221 | void ConfigureInputPlayer::UpdateInputProfiles() { |
| 998 | ui->groupConnectedController->setChecked(connected); | 1222 | ui->comboProfiles->clear(); |
| 1223 | |||
| 1224 | for (const auto& profile_name : profiles->GetInputProfileNames()) { | ||
| 1225 | ui->comboProfiles->addItem(QString::fromStdString(profile_name)); | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | ui->comboProfiles->setCurrentIndex(-1); | ||
| 999 | } | 1229 | } |
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index c19aefffa..23cf6f958 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -26,6 +26,8 @@ class QString; | |||
| 26 | class QTimer; | 26 | class QTimer; |
| 27 | class QWidget; | 27 | class QWidget; |
| 28 | 28 | ||
| 29 | class InputProfiles; | ||
| 30 | |||
| 29 | namespace InputCommon { | 31 | namespace InputCommon { |
| 30 | class InputSubsystem; | 32 | class InputSubsystem; |
| 31 | } | 33 | } |
| @@ -45,14 +47,20 @@ class ConfigureInputPlayer : public QWidget { | |||
| 45 | public: | 47 | public: |
| 46 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, | 48 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, |
| 47 | InputCommon::InputSubsystem* input_subsystem_, | 49 | InputCommon::InputSubsystem* input_subsystem_, |
| 48 | bool debug = false); | 50 | InputProfiles* profiles_, bool debug = false); |
| 49 | ~ConfigureInputPlayer() override; | 51 | ~ConfigureInputPlayer() override; |
| 50 | 52 | ||
| 51 | /// Save all button configurations to settings file. | 53 | /// Save all button configurations to settings file. |
| 52 | void ApplyConfiguration(); | 54 | void ApplyConfiguration(); |
| 53 | 55 | ||
| 56 | /// Set the connection state checkbox (used to sync state). | ||
| 57 | void ConnectPlayer(bool connected); | ||
| 58 | |||
| 54 | /// Update the input devices combobox. | 59 | /// Update the input devices combobox. |
| 55 | void UpdateInputDevices(); | 60 | void UpdateInputDeviceCombobox(); |
| 61 | |||
| 62 | /// Updates the list of controller profiles. | ||
| 63 | void UpdateInputProfiles(); | ||
| 56 | 64 | ||
| 57 | /// Restore all buttons to their default values. | 65 | /// Restore all buttons to their default values. |
| 58 | void RestoreDefaults(); | 66 | void RestoreDefaults(); |
| @@ -60,9 +68,6 @@ public: | |||
| 60 | /// Clear all input configuration. | 68 | /// Clear all input configuration. |
| 61 | void ClearAll(); | 69 | void ClearAll(); |
| 62 | 70 | ||
| 63 | /// Set the connection state checkbox (used to sync state). | ||
| 64 | void ConnectPlayer(bool connected); | ||
| 65 | |||
| 66 | signals: | 71 | signals: |
| 67 | /// Emitted when this controller is connected by the user. | 72 | /// Emitted when this controller is connected by the user. |
| 68 | void Connected(bool connected); | 73 | void Connected(bool connected); |
| @@ -70,6 +75,12 @@ signals: | |||
| 70 | void HandheldStateChanged(bool is_handheld); | 75 | void HandheldStateChanged(bool is_handheld); |
| 71 | /// Emitted when the input devices combobox is being refreshed. | 76 | /// Emitted when the input devices combobox is being refreshed. |
| 72 | void RefreshInputDevices(); | 77 | void RefreshInputDevices(); |
| 78 | /** | ||
| 79 | * Emitted when the input profiles combobox is being refreshed. | ||
| 80 | * The player_index represents the current player's index, and the profile combobox | ||
| 81 | * will not be updated for this index as they are already updated by other mechanisms. | ||
| 82 | */ | ||
| 83 | void RefreshInputProfiles(std::size_t player_index); | ||
| 73 | 84 | ||
| 74 | protected: | 85 | protected: |
| 75 | void showEvent(QShowEvent* event) override; | 86 | void showEvent(QShowEvent* event) override; |
| @@ -89,6 +100,9 @@ private: | |||
| 89 | /// Finish polling and configure input using the input_setter. | 100 | /// Finish polling and configure input using the input_setter. |
| 90 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 101 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 91 | 102 | ||
| 103 | /// Checks whether a given input can be accepted. | ||
| 104 | bool IsInputAcceptable(const Common::ParamPackage& params) const; | ||
| 105 | |||
| 92 | /// Handle mouse button press events. | 106 | /// Handle mouse button press events. |
| 93 | void mousePressEvent(QMouseEvent* event) override; | 107 | void mousePressEvent(QMouseEvent* event) override; |
| 94 | 108 | ||
| @@ -98,8 +112,8 @@ private: | |||
| 98 | /// Update UI to reflect current configuration. | 112 | /// Update UI to reflect current configuration. |
| 99 | void UpdateUI(); | 113 | void UpdateUI(); |
| 100 | 114 | ||
| 101 | /// Update the controller selection combobox | 115 | /// Update the available input devices. |
| 102 | void UpdateControllerCombobox(); | 116 | void UpdateInputDevices(); |
| 103 | 117 | ||
| 104 | /// Update the current controller icon. | 118 | /// Update the current controller icon. |
| 105 | void UpdateControllerIcon(); | 119 | void UpdateControllerIcon(); |
| @@ -113,6 +127,18 @@ private: | |||
| 113 | /// Gets the default controller mapping for this device and auto configures the input to match. | 127 | /// Gets the default controller mapping for this device and auto configures the input to match. |
| 114 | void UpdateMappingWithDefaults(); | 128 | void UpdateMappingWithDefaults(); |
| 115 | 129 | ||
| 130 | /// Creates a controller profile. | ||
| 131 | void CreateProfile(); | ||
| 132 | |||
| 133 | /// Deletes the selected controller profile. | ||
| 134 | void DeleteProfile(); | ||
| 135 | |||
| 136 | /// Loads the selected controller profile. | ||
| 137 | void LoadProfile(); | ||
| 138 | |||
| 139 | /// Saves the current controller configuration into a selected controller profile. | ||
| 140 | void SaveProfile(); | ||
| 141 | |||
| 116 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; | 142 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; |
| 117 | 143 | ||
| 118 | std::size_t player_index; | 144 | std::size_t player_index; |
| @@ -120,6 +146,8 @@ private: | |||
| 120 | 146 | ||
| 121 | InputCommon::InputSubsystem* input_subsystem; | 147 | InputCommon::InputSubsystem* input_subsystem; |
| 122 | 148 | ||
| 149 | InputProfiles* profiles; | ||
| 150 | |||
| 123 | std::unique_ptr<QTimer> timeout_timer; | 151 | std::unique_ptr<QTimer> timeout_timer; |
| 124 | std::unique_ptr<QTimer> poll_timer; | 152 | std::unique_ptr<QTimer> poll_timer; |
| 125 | 153 | ||
| @@ -159,12 +187,15 @@ private: | |||
| 159 | 187 | ||
| 160 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; | 188 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; |
| 161 | 189 | ||
| 190 | /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once. | ||
| 191 | bool map_analog_stick_accepted{}; | ||
| 192 | |||
| 162 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 193 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 163 | /// keyboard events are ignored. | 194 | /// keyboard events are ignored. |
| 164 | bool want_keyboard_mouse = false; | 195 | bool want_keyboard_mouse{}; |
| 165 | 196 | ||
| 166 | /// List of physical devices users can map with. If a SDL backed device is selected, then you | 197 | /// List of physical devices users can map with. If a SDL backed device is selected, then you |
| 167 | /// can usue this device to get a default mapping. | 198 | /// can use this device to get a default mapping. |
| 168 | std::vector<Common::ParamPackage> input_devices; | 199 | std::vector<Common::ParamPackage> input_devices; |
| 169 | 200 | ||
| 170 | /// Bottom row is where console wide settings are held, and its "owned" by the parent | 201 | /// Bottom row is where console wide settings are held, and its "owned" by the parent |
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index e03461d9d..1e78b4c10 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui | |||
| @@ -83,6 +83,12 @@ | |||
| 83 | </property> | 83 | </property> |
| 84 | <item> | 84 | <item> |
| 85 | <widget class="QComboBox" name="comboControllerType"> | 85 | <widget class="QComboBox" name="comboControllerType"> |
| 86 | <property name="minimumSize"> | ||
| 87 | <size> | ||
| 88 | <width>0</width> | ||
| 89 | <height>21</height> | ||
| 90 | </size> | ||
| 91 | </property> | ||
| 86 | <item> | 92 | <item> |
| 87 | <property name="text"> | 93 | <property name="text"> |
| 88 | <string>Pro Controller</string> | 94 | <string>Pro Controller</string> |
| @@ -136,6 +142,12 @@ | |||
| 136 | </property> | 142 | </property> |
| 137 | <item> | 143 | <item> |
| 138 | <widget class="QComboBox" name="comboDevices"> | 144 | <widget class="QComboBox" name="comboDevices"> |
| 145 | <property name="minimumSize"> | ||
| 146 | <size> | ||
| 147 | <width>0</width> | ||
| 148 | <height>21</height> | ||
| 149 | </size> | ||
| 150 | </property> | ||
| 139 | <item> | 151 | <item> |
| 140 | <property name="text"> | 152 | <property name="text"> |
| 141 | <string>Any</string> | 153 | <string>Any</string> |
| @@ -152,14 +164,14 @@ | |||
| 152 | <widget class="QPushButton" name="buttonRefreshDevices"> | 164 | <widget class="QPushButton" name="buttonRefreshDevices"> |
| 153 | <property name="minimumSize"> | 165 | <property name="minimumSize"> |
| 154 | <size> | 166 | <size> |
| 155 | <width>24</width> | 167 | <width>21</width> |
| 156 | <height>22</height> | 168 | <height>21</height> |
| 157 | </size> | 169 | </size> |
| 158 | </property> | 170 | </property> |
| 159 | <property name="maximumSize"> | 171 | <property name="maximumSize"> |
| 160 | <size> | 172 | <size> |
| 161 | <width>24</width> | 173 | <width>21</width> |
| 162 | <height>22</height> | 174 | <height>21</height> |
| 163 | </size> | 175 | </size> |
| 164 | </property> | 176 | </property> |
| 165 | <property name="styleSheet"> | 177 | <property name="styleSheet"> |
| @@ -198,18 +210,25 @@ | |||
| 198 | <number>5</number> | 210 | <number>5</number> |
| 199 | </property> | 211 | </property> |
| 200 | <item> | 212 | <item> |
| 201 | <widget class="QComboBox" name="comboProfiles"/> | 213 | <widget class="QComboBox" name="comboProfiles"> |
| 214 | <property name="minimumSize"> | ||
| 215 | <size> | ||
| 216 | <width>0</width> | ||
| 217 | <height>21</height> | ||
| 218 | </size> | ||
| 219 | </property> | ||
| 220 | </widget> | ||
| 202 | </item> | 221 | </item> |
| 203 | <item> | 222 | <item> |
| 204 | <widget class="QPushButton" name="buttonProfilesSave"> | 223 | <widget class="QPushButton" name="buttonProfilesSave"> |
| 205 | <property name="maximumSize"> | 224 | <property name="maximumSize"> |
| 206 | <size> | 225 | <size> |
| 207 | <width>55</width> | 226 | <width>68</width> |
| 208 | <height>16777215</height> | 227 | <height>16777215</height> |
| 209 | </size> | 228 | </size> |
| 210 | </property> | 229 | </property> |
| 211 | <property name="styleSheet"> | 230 | <property name="styleSheet"> |
| 212 | <string notr="true">min-width: 55px;</string> | 231 | <string notr="true">min-width: 68px;</string> |
| 213 | </property> | 232 | </property> |
| 214 | <property name="text"> | 233 | <property name="text"> |
| 215 | <string>Save</string> | 234 | <string>Save</string> |
| @@ -220,12 +239,12 @@ | |||
| 220 | <widget class="QPushButton" name="buttonProfilesNew"> | 239 | <widget class="QPushButton" name="buttonProfilesNew"> |
| 221 | <property name="maximumSize"> | 240 | <property name="maximumSize"> |
| 222 | <size> | 241 | <size> |
| 223 | <width>55</width> | 242 | <width>68</width> |
| 224 | <height>16777215</height> | 243 | <height>16777215</height> |
| 225 | </size> | 244 | </size> |
| 226 | </property> | 245 | </property> |
| 227 | <property name="styleSheet"> | 246 | <property name="styleSheet"> |
| 228 | <string notr="true">min-width: 55px;</string> | 247 | <string notr="true">min-width: 68px;</string> |
| 229 | </property> | 248 | </property> |
| 230 | <property name="text"> | 249 | <property name="text"> |
| 231 | <string>New</string> | 250 | <string>New</string> |
| @@ -236,12 +255,12 @@ | |||
| 236 | <widget class="QPushButton" name="buttonProfilesDelete"> | 255 | <widget class="QPushButton" name="buttonProfilesDelete"> |
| 237 | <property name="maximumSize"> | 256 | <property name="maximumSize"> |
| 238 | <size> | 257 | <size> |
| 239 | <width>55</width> | 258 | <width>68</width> |
| 240 | <height>16777215</height> | 259 | <height>16777215</height> |
| 241 | </size> | 260 | </size> |
| 242 | </property> | 261 | </property> |
| 243 | <property name="styleSheet"> | 262 | <property name="styleSheet"> |
| 244 | <string notr="true">min-width: 55px;</string> | 263 | <string notr="true">min-width: 68px;</string> |
| 245 | </property> | 264 | </property> |
| 246 | <property name="text"> | 265 | <property name="text"> |
| 247 | <string>Delete</string> | 266 | <string>Delete</string> |
| @@ -393,18 +412,18 @@ | |||
| 393 | <widget class="QPushButton" name="buttonLStickUp"> | 412 | <widget class="QPushButton" name="buttonLStickUp"> |
| 394 | <property name="minimumSize"> | 413 | <property name="minimumSize"> |
| 395 | <size> | 414 | <size> |
| 396 | <width>57</width> | 415 | <width>68</width> |
| 397 | <height>0</height> | 416 | <height>0</height> |
| 398 | </size> | 417 | </size> |
| 399 | </property> | 418 | </property> |
| 400 | <property name="maximumSize"> | 419 | <property name="maximumSize"> |
| 401 | <size> | 420 | <size> |
| 402 | <width>55</width> | 421 | <width>68</width> |
| 403 | <height>16777215</height> | 422 | <height>16777215</height> |
| 404 | </size> | 423 | </size> |
| 405 | </property> | 424 | </property> |
| 406 | <property name="styleSheet"> | 425 | <property name="styleSheet"> |
| 407 | <string notr="true">min-width: 55px;</string> | 426 | <string notr="true">min-width: 68px;</string> |
| 408 | </property> | 427 | </property> |
| 409 | <property name="text"> | 428 | <property name="text"> |
| 410 | <string>Up</string> | 429 | <string>Up</string> |
| @@ -463,18 +482,18 @@ | |||
| 463 | <widget class="QPushButton" name="buttonLStickLeft"> | 482 | <widget class="QPushButton" name="buttonLStickLeft"> |
| 464 | <property name="minimumSize"> | 483 | <property name="minimumSize"> |
| 465 | <size> | 484 | <size> |
| 466 | <width>57</width> | 485 | <width>68</width> |
| 467 | <height>0</height> | 486 | <height>0</height> |
| 468 | </size> | 487 | </size> |
| 469 | </property> | 488 | </property> |
| 470 | <property name="maximumSize"> | 489 | <property name="maximumSize"> |
| 471 | <size> | 490 | <size> |
| 472 | <width>55</width> | 491 | <width>68</width> |
| 473 | <height>16777215</height> | 492 | <height>16777215</height> |
| 474 | </size> | 493 | </size> |
| 475 | </property> | 494 | </property> |
| 476 | <property name="styleSheet"> | 495 | <property name="styleSheet"> |
| 477 | <string notr="true">min-width: 55px;</string> | 496 | <string notr="true">min-width: 68px;</string> |
| 478 | </property> | 497 | </property> |
| 479 | <property name="text"> | 498 | <property name="text"> |
| 480 | <string>Left</string> | 499 | <string>Left</string> |
| @@ -512,18 +531,18 @@ | |||
| 512 | <widget class="QPushButton" name="buttonLStickRight"> | 531 | <widget class="QPushButton" name="buttonLStickRight"> |
| 513 | <property name="minimumSize"> | 532 | <property name="minimumSize"> |
| 514 | <size> | 533 | <size> |
| 515 | <width>57</width> | 534 | <width>68</width> |
| 516 | <height>0</height> | 535 | <height>0</height> |
| 517 | </size> | 536 | </size> |
| 518 | </property> | 537 | </property> |
| 519 | <property name="maximumSize"> | 538 | <property name="maximumSize"> |
| 520 | <size> | 539 | <size> |
| 521 | <width>55</width> | 540 | <width>68</width> |
| 522 | <height>16777215</height> | 541 | <height>16777215</height> |
| 523 | </size> | 542 | </size> |
| 524 | </property> | 543 | </property> |
| 525 | <property name="styleSheet"> | 544 | <property name="styleSheet"> |
| 526 | <string notr="true">min-width: 55px;</string> | 545 | <string notr="true">min-width: 68px;</string> |
| 527 | </property> | 546 | </property> |
| 528 | <property name="text"> | 547 | <property name="text"> |
| 529 | <string>Right</string> | 548 | <string>Right</string> |
| @@ -594,18 +613,18 @@ | |||
| 594 | <widget class="QPushButton" name="buttonLStickDown"> | 613 | <widget class="QPushButton" name="buttonLStickDown"> |
| 595 | <property name="minimumSize"> | 614 | <property name="minimumSize"> |
| 596 | <size> | 615 | <size> |
| 597 | <width>57</width> | 616 | <width>68</width> |
| 598 | <height>0</height> | 617 | <height>0</height> |
| 599 | </size> | 618 | </size> |
| 600 | </property> | 619 | </property> |
| 601 | <property name="maximumSize"> | 620 | <property name="maximumSize"> |
| 602 | <size> | 621 | <size> |
| 603 | <width>55</width> | 622 | <width>68</width> |
| 604 | <height>16777215</height> | 623 | <height>16777215</height> |
| 605 | </size> | 624 | </size> |
| 606 | </property> | 625 | </property> |
| 607 | <property name="styleSheet"> | 626 | <property name="styleSheet"> |
| 608 | <string notr="true">min-width: 55px;</string> | 627 | <string notr="true">min-width: 68px;</string> |
| 609 | </property> | 628 | </property> |
| 610 | <property name="text"> | 629 | <property name="text"> |
| 611 | <string>Down</string> | 630 | <string>Down</string> |
| @@ -664,18 +683,18 @@ | |||
| 664 | <widget class="QPushButton" name="buttonLStick"> | 683 | <widget class="QPushButton" name="buttonLStick"> |
| 665 | <property name="minimumSize"> | 684 | <property name="minimumSize"> |
| 666 | <size> | 685 | <size> |
| 667 | <width>57</width> | 686 | <width>68</width> |
| 668 | <height>0</height> | 687 | <height>0</height> |
| 669 | </size> | 688 | </size> |
| 670 | </property> | 689 | </property> |
| 671 | <property name="maximumSize"> | 690 | <property name="maximumSize"> |
| 672 | <size> | 691 | <size> |
| 673 | <width>55</width> | 692 | <width>68</width> |
| 674 | <height>16777215</height> | 693 | <height>16777215</height> |
| 675 | </size> | 694 | </size> |
| 676 | </property> | 695 | </property> |
| 677 | <property name="styleSheet"> | 696 | <property name="styleSheet"> |
| 678 | <string notr="true">min-width: 55px;</string> | 697 | <string notr="true">min-width: 68px;</string> |
| 679 | </property> | 698 | </property> |
| 680 | <property name="text"> | 699 | <property name="text"> |
| 681 | <string>Pressed</string> | 700 | <string>Pressed</string> |
| @@ -713,18 +732,18 @@ | |||
| 713 | <widget class="QPushButton" name="buttonLStickMod"> | 732 | <widget class="QPushButton" name="buttonLStickMod"> |
| 714 | <property name="minimumSize"> | 733 | <property name="minimumSize"> |
| 715 | <size> | 734 | <size> |
| 716 | <width>57</width> | 735 | <width>68</width> |
| 717 | <height>0</height> | 736 | <height>0</height> |
| 718 | </size> | 737 | </size> |
| 719 | </property> | 738 | </property> |
| 720 | <property name="maximumSize"> | 739 | <property name="maximumSize"> |
| 721 | <size> | 740 | <size> |
| 722 | <width>55</width> | 741 | <width>68</width> |
| 723 | <height>16777215</height> | 742 | <height>16777215</height> |
| 724 | </size> | 743 | </size> |
| 725 | </property> | 744 | </property> |
| 726 | <property name="styleSheet"> | 745 | <property name="styleSheet"> |
| 727 | <string notr="true">min-width: 55px;</string> | 746 | <string notr="true">min-width: 68px;</string> |
| 728 | </property> | 747 | </property> |
| 729 | <property name="text"> | 748 | <property name="text"> |
| 730 | <string>Modifier</string> | 749 | <string>Modifier</string> |
| @@ -759,13 +778,13 @@ | |||
| 759 | <widget class="QSpinBox" name="spinboxLStickRange"> | 778 | <widget class="QSpinBox" name="spinboxLStickRange"> |
| 760 | <property name="minimumSize"> | 779 | <property name="minimumSize"> |
| 761 | <size> | 780 | <size> |
| 762 | <width>55</width> | 781 | <width>68</width> |
| 763 | <height>21</height> | 782 | <height>21</height> |
| 764 | </size> | 783 | </size> |
| 765 | </property> | 784 | </property> |
| 766 | <property name="maximumSize"> | 785 | <property name="maximumSize"> |
| 767 | <size> | 786 | <size> |
| 768 | <width>55</width> | 787 | <width>68</width> |
| 769 | <height>16777215</height> | 788 | <height>16777215</height> |
| 770 | </size> | 789 | </size> |
| 771 | </property> | 790 | </property> |
| @@ -966,18 +985,18 @@ | |||
| 966 | <widget class="QPushButton" name="buttonDpadUp"> | 985 | <widget class="QPushButton" name="buttonDpadUp"> |
| 967 | <property name="minimumSize"> | 986 | <property name="minimumSize"> |
| 968 | <size> | 987 | <size> |
| 969 | <width>57</width> | 988 | <width>68</width> |
| 970 | <height>0</height> | 989 | <height>0</height> |
| 971 | </size> | 990 | </size> |
| 972 | </property> | 991 | </property> |
| 973 | <property name="maximumSize"> | 992 | <property name="maximumSize"> |
| 974 | <size> | 993 | <size> |
| 975 | <width>55</width> | 994 | <width>68</width> |
| 976 | <height>16777215</height> | 995 | <height>16777215</height> |
| 977 | </size> | 996 | </size> |
| 978 | </property> | 997 | </property> |
| 979 | <property name="styleSheet"> | 998 | <property name="styleSheet"> |
| 980 | <string notr="true">min-width: 55px;</string> | 999 | <string notr="true">min-width: 68px;</string> |
| 981 | </property> | 1000 | </property> |
| 982 | <property name="text"> | 1001 | <property name="text"> |
| 983 | <string>Up</string> | 1002 | <string>Up</string> |
| @@ -1036,18 +1055,18 @@ | |||
| 1036 | <widget class="QPushButton" name="buttonDpadLeft"> | 1055 | <widget class="QPushButton" name="buttonDpadLeft"> |
| 1037 | <property name="minimumSize"> | 1056 | <property name="minimumSize"> |
| 1038 | <size> | 1057 | <size> |
| 1039 | <width>57</width> | 1058 | <width>68</width> |
| 1040 | <height>0</height> | 1059 | <height>0</height> |
| 1041 | </size> | 1060 | </size> |
| 1042 | </property> | 1061 | </property> |
| 1043 | <property name="maximumSize"> | 1062 | <property name="maximumSize"> |
| 1044 | <size> | 1063 | <size> |
| 1045 | <width>55</width> | 1064 | <width>68</width> |
| 1046 | <height>16777215</height> | 1065 | <height>16777215</height> |
| 1047 | </size> | 1066 | </size> |
| 1048 | </property> | 1067 | </property> |
| 1049 | <property name="styleSheet"> | 1068 | <property name="styleSheet"> |
| 1050 | <string notr="true">min-width: 55px;</string> | 1069 | <string notr="true">min-width: 68px;</string> |
| 1051 | </property> | 1070 | </property> |
| 1052 | <property name="text"> | 1071 | <property name="text"> |
| 1053 | <string>Left</string> | 1072 | <string>Left</string> |
| @@ -1085,18 +1104,18 @@ | |||
| 1085 | <widget class="QPushButton" name="buttonDpadRight"> | 1104 | <widget class="QPushButton" name="buttonDpadRight"> |
| 1086 | <property name="minimumSize"> | 1105 | <property name="minimumSize"> |
| 1087 | <size> | 1106 | <size> |
| 1088 | <width>57</width> | 1107 | <width>68</width> |
| 1089 | <height>0</height> | 1108 | <height>0</height> |
| 1090 | </size> | 1109 | </size> |
| 1091 | </property> | 1110 | </property> |
| 1092 | <property name="maximumSize"> | 1111 | <property name="maximumSize"> |
| 1093 | <size> | 1112 | <size> |
| 1094 | <width>55</width> | 1113 | <width>68</width> |
| 1095 | <height>16777215</height> | 1114 | <height>16777215</height> |
| 1096 | </size> | 1115 | </size> |
| 1097 | </property> | 1116 | </property> |
| 1098 | <property name="styleSheet"> | 1117 | <property name="styleSheet"> |
| 1099 | <string notr="true">min-width: 55px;</string> | 1118 | <string notr="true">min-width: 68px;</string> |
| 1100 | </property> | 1119 | </property> |
| 1101 | <property name="text"> | 1120 | <property name="text"> |
| 1102 | <string>Right</string> | 1121 | <string>Right</string> |
| @@ -1167,18 +1186,18 @@ | |||
| 1167 | <widget class="QPushButton" name="buttonDpadDown"> | 1186 | <widget class="QPushButton" name="buttonDpadDown"> |
| 1168 | <property name="minimumSize"> | 1187 | <property name="minimumSize"> |
| 1169 | <size> | 1188 | <size> |
| 1170 | <width>57</width> | 1189 | <width>68</width> |
| 1171 | <height>0</height> | 1190 | <height>0</height> |
| 1172 | </size> | 1191 | </size> |
| 1173 | </property> | 1192 | </property> |
| 1174 | <property name="maximumSize"> | 1193 | <property name="maximumSize"> |
| 1175 | <size> | 1194 | <size> |
| 1176 | <width>55</width> | 1195 | <width>68</width> |
| 1177 | <height>16777215</height> | 1196 | <height>16777215</height> |
| 1178 | </size> | 1197 | </size> |
| 1179 | </property> | 1198 | </property> |
| 1180 | <property name="styleSheet"> | 1199 | <property name="styleSheet"> |
| 1181 | <string notr="true">min-width: 55px;</string> | 1200 | <string notr="true">min-width: 68px;</string> |
| 1182 | </property> | 1201 | </property> |
| 1183 | <property name="text"> | 1202 | <property name="text"> |
| 1184 | <string>Down</string> | 1203 | <string>Down</string> |
| @@ -1292,18 +1311,18 @@ | |||
| 1292 | <widget class="QPushButton" name="buttonL"> | 1311 | <widget class="QPushButton" name="buttonL"> |
| 1293 | <property name="minimumSize"> | 1312 | <property name="minimumSize"> |
| 1294 | <size> | 1313 | <size> |
| 1295 | <width>57</width> | 1314 | <width>68</width> |
| 1296 | <height>0</height> | 1315 | <height>0</height> |
| 1297 | </size> | 1316 | </size> |
| 1298 | </property> | 1317 | </property> |
| 1299 | <property name="maximumSize"> | 1318 | <property name="maximumSize"> |
| 1300 | <size> | 1319 | <size> |
| 1301 | <width>55</width> | 1320 | <width>68</width> |
| 1302 | <height>16777215</height> | 1321 | <height>16777215</height> |
| 1303 | </size> | 1322 | </size> |
| 1304 | </property> | 1323 | </property> |
| 1305 | <property name="styleSheet"> | 1324 | <property name="styleSheet"> |
| 1306 | <string notr="true">min-width: 55px;</string> | 1325 | <string notr="true">min-width: 68px;</string> |
| 1307 | </property> | 1326 | </property> |
| 1308 | <property name="text"> | 1327 | <property name="text"> |
| 1309 | <string>L</string> | 1328 | <string>L</string> |
| @@ -1341,18 +1360,18 @@ | |||
| 1341 | <widget class="QPushButton" name="buttonZL"> | 1360 | <widget class="QPushButton" name="buttonZL"> |
| 1342 | <property name="minimumSize"> | 1361 | <property name="minimumSize"> |
| 1343 | <size> | 1362 | <size> |
| 1344 | <width>57</width> | 1363 | <width>68</width> |
| 1345 | <height>0</height> | 1364 | <height>0</height> |
| 1346 | </size> | 1365 | </size> |
| 1347 | </property> | 1366 | </property> |
| 1348 | <property name="maximumSize"> | 1367 | <property name="maximumSize"> |
| 1349 | <size> | 1368 | <size> |
| 1350 | <width>55</width> | 1369 | <width>68</width> |
| 1351 | <height>16777215</height> | 1370 | <height>16777215</height> |
| 1352 | </size> | 1371 | </size> |
| 1353 | </property> | 1372 | </property> |
| 1354 | <property name="styleSheet"> | 1373 | <property name="styleSheet"> |
| 1355 | <string notr="true">min-width: 55px;</string> | 1374 | <string notr="true">min-width: 68px;</string> |
| 1356 | </property> | 1375 | </property> |
| 1357 | <property name="text"> | 1376 | <property name="text"> |
| 1358 | <string>ZL</string> | 1377 | <string>ZL</string> |
| @@ -1445,18 +1464,18 @@ | |||
| 1445 | <widget class="QPushButton" name="buttonMinus"> | 1464 | <widget class="QPushButton" name="buttonMinus"> |
| 1446 | <property name="minimumSize"> | 1465 | <property name="minimumSize"> |
| 1447 | <size> | 1466 | <size> |
| 1448 | <width>57</width> | 1467 | <width>68</width> |
| 1449 | <height>0</height> | 1468 | <height>0</height> |
| 1450 | </size> | 1469 | </size> |
| 1451 | </property> | 1470 | </property> |
| 1452 | <property name="maximumSize"> | 1471 | <property name="maximumSize"> |
| 1453 | <size> | 1472 | <size> |
| 1454 | <width>55</width> | 1473 | <width>68</width> |
| 1455 | <height>16777215</height> | 1474 | <height>16777215</height> |
| 1456 | </size> | 1475 | </size> |
| 1457 | </property> | 1476 | </property> |
| 1458 | <property name="styleSheet"> | 1477 | <property name="styleSheet"> |
| 1459 | <string notr="true">min-width: 55px;</string> | 1478 | <string notr="true">min-width: 68px;</string> |
| 1460 | </property> | 1479 | </property> |
| 1461 | <property name="text"> | 1480 | <property name="text"> |
| 1462 | <string>Minus</string> | 1481 | <string>Minus</string> |
| @@ -1494,18 +1513,18 @@ | |||
| 1494 | <widget class="QPushButton" name="buttonScreenshot"> | 1513 | <widget class="QPushButton" name="buttonScreenshot"> |
| 1495 | <property name="minimumSize"> | 1514 | <property name="minimumSize"> |
| 1496 | <size> | 1515 | <size> |
| 1497 | <width>57</width> | 1516 | <width>68</width> |
| 1498 | <height>0</height> | 1517 | <height>0</height> |
| 1499 | </size> | 1518 | </size> |
| 1500 | </property> | 1519 | </property> |
| 1501 | <property name="maximumSize"> | 1520 | <property name="maximumSize"> |
| 1502 | <size> | 1521 | <size> |
| 1503 | <width>55</width> | 1522 | <width>68</width> |
| 1504 | <height>16777215</height> | 1523 | <height>16777215</height> |
| 1505 | </size> | 1524 | </size> |
| 1506 | </property> | 1525 | </property> |
| 1507 | <property name="styleSheet"> | 1526 | <property name="styleSheet"> |
| 1508 | <string notr="true">min-width: 55px;</string> | 1527 | <string notr="true">min-width: 68px;</string> |
| 1509 | </property> | 1528 | </property> |
| 1510 | <property name="text"> | 1529 | <property name="text"> |
| 1511 | <string>Capture</string> | 1530 | <string>Capture</string> |
| @@ -1564,18 +1583,18 @@ | |||
| 1564 | <widget class="QPushButton" name="buttonPlus"> | 1583 | <widget class="QPushButton" name="buttonPlus"> |
| 1565 | <property name="minimumSize"> | 1584 | <property name="minimumSize"> |
| 1566 | <size> | 1585 | <size> |
| 1567 | <width>57</width> | 1586 | <width>68</width> |
| 1568 | <height>0</height> | 1587 | <height>0</height> |
| 1569 | </size> | 1588 | </size> |
| 1570 | </property> | 1589 | </property> |
| 1571 | <property name="maximumSize"> | 1590 | <property name="maximumSize"> |
| 1572 | <size> | 1591 | <size> |
| 1573 | <width>55</width> | 1592 | <width>68</width> |
| 1574 | <height>16777215</height> | 1593 | <height>16777215</height> |
| 1575 | </size> | 1594 | </size> |
| 1576 | </property> | 1595 | </property> |
| 1577 | <property name="styleSheet"> | 1596 | <property name="styleSheet"> |
| 1578 | <string notr="true">min-width: 55px;</string> | 1597 | <string notr="true">min-width: 68px;</string> |
| 1579 | </property> | 1598 | </property> |
| 1580 | <property name="text"> | 1599 | <property name="text"> |
| 1581 | <string>Plus</string> | 1600 | <string>Plus</string> |
| @@ -1613,18 +1632,18 @@ | |||
| 1613 | <widget class="QPushButton" name="buttonHome"> | 1632 | <widget class="QPushButton" name="buttonHome"> |
| 1614 | <property name="minimumSize"> | 1633 | <property name="minimumSize"> |
| 1615 | <size> | 1634 | <size> |
| 1616 | <width>57</width> | 1635 | <width>68</width> |
| 1617 | <height>0</height> | 1636 | <height>0</height> |
| 1618 | </size> | 1637 | </size> |
| 1619 | </property> | 1638 | </property> |
| 1620 | <property name="maximumSize"> | 1639 | <property name="maximumSize"> |
| 1621 | <size> | 1640 | <size> |
| 1622 | <width>55</width> | 1641 | <width>68</width> |
| 1623 | <height>16777215</height> | 1642 | <height>16777215</height> |
| 1624 | </size> | 1643 | </size> |
| 1625 | </property> | 1644 | </property> |
| 1626 | <property name="styleSheet"> | 1645 | <property name="styleSheet"> |
| 1627 | <string notr="true">min-width: 55px;</string> | 1646 | <string notr="true">min-width: 68px;</string> |
| 1628 | </property> | 1647 | </property> |
| 1629 | <property name="text"> | 1648 | <property name="text"> |
| 1630 | <string>Home</string> | 1649 | <string>Home</string> |
| @@ -1717,18 +1736,18 @@ | |||
| 1717 | <widget class="QPushButton" name="buttonR"> | 1736 | <widget class="QPushButton" name="buttonR"> |
| 1718 | <property name="minimumSize"> | 1737 | <property name="minimumSize"> |
| 1719 | <size> | 1738 | <size> |
| 1720 | <width>57</width> | 1739 | <width>68</width> |
| 1721 | <height>0</height> | 1740 | <height>0</height> |
| 1722 | </size> | 1741 | </size> |
| 1723 | </property> | 1742 | </property> |
| 1724 | <property name="maximumSize"> | 1743 | <property name="maximumSize"> |
| 1725 | <size> | 1744 | <size> |
| 1726 | <width>55</width> | 1745 | <width>68</width> |
| 1727 | <height>16777215</height> | 1746 | <height>16777215</height> |
| 1728 | </size> | 1747 | </size> |
| 1729 | </property> | 1748 | </property> |
| 1730 | <property name="styleSheet"> | 1749 | <property name="styleSheet"> |
| 1731 | <string notr="true">min-width: 55px;</string> | 1750 | <string notr="true">min-width: 68px;</string> |
| 1732 | </property> | 1751 | </property> |
| 1733 | <property name="text"> | 1752 | <property name="text"> |
| 1734 | <string>R</string> | 1753 | <string>R</string> |
| @@ -1766,18 +1785,18 @@ | |||
| 1766 | <widget class="QPushButton" name="buttonZR"> | 1785 | <widget class="QPushButton" name="buttonZR"> |
| 1767 | <property name="minimumSize"> | 1786 | <property name="minimumSize"> |
| 1768 | <size> | 1787 | <size> |
| 1769 | <width>57</width> | 1788 | <width>68</width> |
| 1770 | <height>0</height> | 1789 | <height>0</height> |
| 1771 | </size> | 1790 | </size> |
| 1772 | </property> | 1791 | </property> |
| 1773 | <property name="maximumSize"> | 1792 | <property name="maximumSize"> |
| 1774 | <size> | 1793 | <size> |
| 1775 | <width>55</width> | 1794 | <width>68</width> |
| 1776 | <height>16777215</height> | 1795 | <height>16777215</height> |
| 1777 | </size> | 1796 | </size> |
| 1778 | </property> | 1797 | </property> |
| 1779 | <property name="styleSheet"> | 1798 | <property name="styleSheet"> |
| 1780 | <string notr="true">min-width: 55px;</string> | 1799 | <string notr="true">min-width: 68px;</string> |
| 1781 | </property> | 1800 | </property> |
| 1782 | <property name="text"> | 1801 | <property name="text"> |
| 1783 | <string>ZR</string> | 1802 | <string>ZR</string> |
| @@ -1870,18 +1889,18 @@ | |||
| 1870 | <widget class="QPushButton" name="buttonSL"> | 1889 | <widget class="QPushButton" name="buttonSL"> |
| 1871 | <property name="minimumSize"> | 1890 | <property name="minimumSize"> |
| 1872 | <size> | 1891 | <size> |
| 1873 | <width>57</width> | 1892 | <width>68</width> |
| 1874 | <height>0</height> | 1893 | <height>0</height> |
| 1875 | </size> | 1894 | </size> |
| 1876 | </property> | 1895 | </property> |
| 1877 | <property name="maximumSize"> | 1896 | <property name="maximumSize"> |
| 1878 | <size> | 1897 | <size> |
| 1879 | <width>55</width> | 1898 | <width>68</width> |
| 1880 | <height>16777215</height> | 1899 | <height>16777215</height> |
| 1881 | </size> | 1900 | </size> |
| 1882 | </property> | 1901 | </property> |
| 1883 | <property name="styleSheet"> | 1902 | <property name="styleSheet"> |
| 1884 | <string notr="true">min-width: 55px;</string> | 1903 | <string notr="true">min-width: 68px;</string> |
| 1885 | </property> | 1904 | </property> |
| 1886 | <property name="text"> | 1905 | <property name="text"> |
| 1887 | <string>SL</string> | 1906 | <string>SL</string> |
| @@ -1919,18 +1938,18 @@ | |||
| 1919 | <widget class="QPushButton" name="buttonSR"> | 1938 | <widget class="QPushButton" name="buttonSR"> |
| 1920 | <property name="minimumSize"> | 1939 | <property name="minimumSize"> |
| 1921 | <size> | 1940 | <size> |
| 1922 | <width>57</width> | 1941 | <width>68</width> |
| 1923 | <height>0</height> | 1942 | <height>0</height> |
| 1924 | </size> | 1943 | </size> |
| 1925 | </property> | 1944 | </property> |
| 1926 | <property name="maximumSize"> | 1945 | <property name="maximumSize"> |
| 1927 | <size> | 1946 | <size> |
| 1928 | <width>55</width> | 1947 | <width>68</width> |
| 1929 | <height>16777215</height> | 1948 | <height>16777215</height> |
| 1930 | </size> | 1949 | </size> |
| 1931 | </property> | 1950 | </property> |
| 1932 | <property name="styleSheet"> | 1951 | <property name="styleSheet"> |
| 1933 | <string notr="true">min-width: 55px;</string> | 1952 | <string notr="true">min-width: 68px;</string> |
| 1934 | </property> | 1953 | </property> |
| 1935 | <property name="text"> | 1954 | <property name="text"> |
| 1936 | <string>SR</string> | 1955 | <string>SR</string> |
| @@ -2027,18 +2046,18 @@ | |||
| 2027 | <widget class="QPushButton" name="buttonMotionLeft"> | 2046 | <widget class="QPushButton" name="buttonMotionLeft"> |
| 2028 | <property name="minimumSize"> | 2047 | <property name="minimumSize"> |
| 2029 | <size> | 2048 | <size> |
| 2030 | <width>57</width> | 2049 | <width>68</width> |
| 2031 | <height>0</height> | 2050 | <height>0</height> |
| 2032 | </size> | 2051 | </size> |
| 2033 | </property> | 2052 | </property> |
| 2034 | <property name="maximumSize"> | 2053 | <property name="maximumSize"> |
| 2035 | <size> | 2054 | <size> |
| 2036 | <width>55</width> | 2055 | <width>68</width> |
| 2037 | <height>16777215</height> | 2056 | <height>16777215</height> |
| 2038 | </size> | 2057 | </size> |
| 2039 | </property> | 2058 | </property> |
| 2040 | <property name="styleSheet"> | 2059 | <property name="styleSheet"> |
| 2041 | <string notr="true">min-width: 55px;</string> | 2060 | <string notr="true">min-width: 68px;</string> |
| 2042 | </property> | 2061 | </property> |
| 2043 | <property name="text"> | 2062 | <property name="text"> |
| 2044 | <string>Left</string> | 2063 | <string>Left</string> |
| @@ -2076,18 +2095,18 @@ | |||
| 2076 | <widget class="QPushButton" name="buttonMotionRight"> | 2095 | <widget class="QPushButton" name="buttonMotionRight"> |
| 2077 | <property name="minimumSize"> | 2096 | <property name="minimumSize"> |
| 2078 | <size> | 2097 | <size> |
| 2079 | <width>57</width> | 2098 | <width>68</width> |
| 2080 | <height>0</height> | 2099 | <height>0</height> |
| 2081 | </size> | 2100 | </size> |
| 2082 | </property> | 2101 | </property> |
| 2083 | <property name="maximumSize"> | 2102 | <property name="maximumSize"> |
| 2084 | <size> | 2103 | <size> |
| 2085 | <width>55</width> | 2104 | <width>68</width> |
| 2086 | <height>16777215</height> | 2105 | <height>16777215</height> |
| 2087 | </size> | 2106 | </size> |
| 2088 | </property> | 2107 | </property> |
| 2089 | <property name="styleSheet"> | 2108 | <property name="styleSheet"> |
| 2090 | <string notr="true">min-width: 55px;</string> | 2109 | <string notr="true">min-width: 68px;</string> |
| 2091 | </property> | 2110 | </property> |
| 2092 | <property name="text"> | 2111 | <property name="text"> |
| 2093 | <string>Right</string> | 2112 | <string>Right</string> |
| @@ -2225,18 +2244,18 @@ | |||
| 2225 | <widget class="QPushButton" name="buttonX"> | 2244 | <widget class="QPushButton" name="buttonX"> |
| 2226 | <property name="minimumSize"> | 2245 | <property name="minimumSize"> |
| 2227 | <size> | 2246 | <size> |
| 2228 | <width>57</width> | 2247 | <width>68</width> |
| 2229 | <height>0</height> | 2248 | <height>0</height> |
| 2230 | </size> | 2249 | </size> |
| 2231 | </property> | 2250 | </property> |
| 2232 | <property name="maximumSize"> | 2251 | <property name="maximumSize"> |
| 2233 | <size> | 2252 | <size> |
| 2234 | <width>55</width> | 2253 | <width>68</width> |
| 2235 | <height>16777215</height> | 2254 | <height>16777215</height> |
| 2236 | </size> | 2255 | </size> |
| 2237 | </property> | 2256 | </property> |
| 2238 | <property name="styleSheet"> | 2257 | <property name="styleSheet"> |
| 2239 | <string notr="true">min-width: 55px;</string> | 2258 | <string notr="true">min-width: 68px;</string> |
| 2240 | </property> | 2259 | </property> |
| 2241 | <property name="text"> | 2260 | <property name="text"> |
| 2242 | <string>X</string> | 2261 | <string>X</string> |
| @@ -2295,18 +2314,18 @@ | |||
| 2295 | <widget class="QPushButton" name="buttonY"> | 2314 | <widget class="QPushButton" name="buttonY"> |
| 2296 | <property name="minimumSize"> | 2315 | <property name="minimumSize"> |
| 2297 | <size> | 2316 | <size> |
| 2298 | <width>57</width> | 2317 | <width>68</width> |
| 2299 | <height>0</height> | 2318 | <height>0</height> |
| 2300 | </size> | 2319 | </size> |
| 2301 | </property> | 2320 | </property> |
| 2302 | <property name="maximumSize"> | 2321 | <property name="maximumSize"> |
| 2303 | <size> | 2322 | <size> |
| 2304 | <width>55</width> | 2323 | <width>68</width> |
| 2305 | <height>16777215</height> | 2324 | <height>16777215</height> |
| 2306 | </size> | 2325 | </size> |
| 2307 | </property> | 2326 | </property> |
| 2308 | <property name="styleSheet"> | 2327 | <property name="styleSheet"> |
| 2309 | <string notr="true">min-width: 55px;</string> | 2328 | <string notr="true">min-width: 68px;</string> |
| 2310 | </property> | 2329 | </property> |
| 2311 | <property name="text"> | 2330 | <property name="text"> |
| 2312 | <string>Y</string> | 2331 | <string>Y</string> |
| @@ -2344,18 +2363,18 @@ | |||
| 2344 | <widget class="QPushButton" name="buttonA"> | 2363 | <widget class="QPushButton" name="buttonA"> |
| 2345 | <property name="minimumSize"> | 2364 | <property name="minimumSize"> |
| 2346 | <size> | 2365 | <size> |
| 2347 | <width>57</width> | 2366 | <width>68</width> |
| 2348 | <height>0</height> | 2367 | <height>0</height> |
| 2349 | </size> | 2368 | </size> |
| 2350 | </property> | 2369 | </property> |
| 2351 | <property name="maximumSize"> | 2370 | <property name="maximumSize"> |
| 2352 | <size> | 2371 | <size> |
| 2353 | <width>55</width> | 2372 | <width>68</width> |
| 2354 | <height>16777215</height> | 2373 | <height>16777215</height> |
| 2355 | </size> | 2374 | </size> |
| 2356 | </property> | 2375 | </property> |
| 2357 | <property name="styleSheet"> | 2376 | <property name="styleSheet"> |
| 2358 | <string notr="true">min-width: 55px;</string> | 2377 | <string notr="true">min-width: 68px;</string> |
| 2359 | </property> | 2378 | </property> |
| 2360 | <property name="text"> | 2379 | <property name="text"> |
| 2361 | <string>A</string> | 2380 | <string>A</string> |
| @@ -2426,18 +2445,18 @@ | |||
| 2426 | <widget class="QPushButton" name="buttonB"> | 2445 | <widget class="QPushButton" name="buttonB"> |
| 2427 | <property name="minimumSize"> | 2446 | <property name="minimumSize"> |
| 2428 | <size> | 2447 | <size> |
| 2429 | <width>57</width> | 2448 | <width>68</width> |
| 2430 | <height>0</height> | 2449 | <height>0</height> |
| 2431 | </size> | 2450 | </size> |
| 2432 | </property> | 2451 | </property> |
| 2433 | <property name="maximumSize"> | 2452 | <property name="maximumSize"> |
| 2434 | <size> | 2453 | <size> |
| 2435 | <width>55</width> | 2454 | <width>68</width> |
| 2436 | <height>16777215</height> | 2455 | <height>16777215</height> |
| 2437 | </size> | 2456 | </size> |
| 2438 | </property> | 2457 | </property> |
| 2439 | <property name="styleSheet"> | 2458 | <property name="styleSheet"> |
| 2440 | <string notr="true">min-width: 55px;</string> | 2459 | <string notr="true">min-width: 68px;</string> |
| 2441 | </property> | 2460 | </property> |
| 2442 | <property name="text"> | 2461 | <property name="text"> |
| 2443 | <string>B</string> | 2462 | <string>B</string> |
| @@ -2580,18 +2599,18 @@ | |||
| 2580 | <widget class="QPushButton" name="buttonRStickUp"> | 2599 | <widget class="QPushButton" name="buttonRStickUp"> |
| 2581 | <property name="minimumSize"> | 2600 | <property name="minimumSize"> |
| 2582 | <size> | 2601 | <size> |
| 2583 | <width>57</width> | 2602 | <width>68</width> |
| 2584 | <height>0</height> | 2603 | <height>0</height> |
| 2585 | </size> | 2604 | </size> |
| 2586 | </property> | 2605 | </property> |
| 2587 | <property name="maximumSize"> | 2606 | <property name="maximumSize"> |
| 2588 | <size> | 2607 | <size> |
| 2589 | <width>55</width> | 2608 | <width>68</width> |
| 2590 | <height>16777215</height> | 2609 | <height>16777215</height> |
| 2591 | </size> | 2610 | </size> |
| 2592 | </property> | 2611 | </property> |
| 2593 | <property name="styleSheet"> | 2612 | <property name="styleSheet"> |
| 2594 | <string notr="true">min-width: 55px;</string> | 2613 | <string notr="true">min-width: 68px;</string> |
| 2595 | </property> | 2614 | </property> |
| 2596 | <property name="text"> | 2615 | <property name="text"> |
| 2597 | <string>Up</string> | 2616 | <string>Up</string> |
| @@ -2650,18 +2669,18 @@ | |||
| 2650 | <widget class="QPushButton" name="buttonRStickLeft"> | 2669 | <widget class="QPushButton" name="buttonRStickLeft"> |
| 2651 | <property name="minimumSize"> | 2670 | <property name="minimumSize"> |
| 2652 | <size> | 2671 | <size> |
| 2653 | <width>57</width> | 2672 | <width>68</width> |
| 2654 | <height>0</height> | 2673 | <height>0</height> |
| 2655 | </size> | 2674 | </size> |
| 2656 | </property> | 2675 | </property> |
| 2657 | <property name="maximumSize"> | 2676 | <property name="maximumSize"> |
| 2658 | <size> | 2677 | <size> |
| 2659 | <width>55</width> | 2678 | <width>68</width> |
| 2660 | <height>16777215</height> | 2679 | <height>16777215</height> |
| 2661 | </size> | 2680 | </size> |
| 2662 | </property> | 2681 | </property> |
| 2663 | <property name="styleSheet"> | 2682 | <property name="styleSheet"> |
| 2664 | <string notr="true">min-width: 55px;</string> | 2683 | <string notr="true">min-width: 68px;</string> |
| 2665 | </property> | 2684 | </property> |
| 2666 | <property name="text"> | 2685 | <property name="text"> |
| 2667 | <string>Left</string> | 2686 | <string>Left</string> |
| @@ -2699,18 +2718,18 @@ | |||
| 2699 | <widget class="QPushButton" name="buttonRStickRight"> | 2718 | <widget class="QPushButton" name="buttonRStickRight"> |
| 2700 | <property name="minimumSize"> | 2719 | <property name="minimumSize"> |
| 2701 | <size> | 2720 | <size> |
| 2702 | <width>57</width> | 2721 | <width>68</width> |
| 2703 | <height>0</height> | 2722 | <height>0</height> |
| 2704 | </size> | 2723 | </size> |
| 2705 | </property> | 2724 | </property> |
| 2706 | <property name="maximumSize"> | 2725 | <property name="maximumSize"> |
| 2707 | <size> | 2726 | <size> |
| 2708 | <width>55</width> | 2727 | <width>68</width> |
| 2709 | <height>16777215</height> | 2728 | <height>16777215</height> |
| 2710 | </size> | 2729 | </size> |
| 2711 | </property> | 2730 | </property> |
| 2712 | <property name="styleSheet"> | 2731 | <property name="styleSheet"> |
| 2713 | <string notr="true">min-width: 55px;</string> | 2732 | <string notr="true">min-width: 68px;</string> |
| 2714 | </property> | 2733 | </property> |
| 2715 | <property name="text"> | 2734 | <property name="text"> |
| 2716 | <string>Right</string> | 2735 | <string>Right</string> |
| @@ -2781,18 +2800,18 @@ | |||
| 2781 | <widget class="QPushButton" name="buttonRStickDown"> | 2800 | <widget class="QPushButton" name="buttonRStickDown"> |
| 2782 | <property name="minimumSize"> | 2801 | <property name="minimumSize"> |
| 2783 | <size> | 2802 | <size> |
| 2784 | <width>57</width> | 2803 | <width>68</width> |
| 2785 | <height>0</height> | 2804 | <height>0</height> |
| 2786 | </size> | 2805 | </size> |
| 2787 | </property> | 2806 | </property> |
| 2788 | <property name="maximumSize"> | 2807 | <property name="maximumSize"> |
| 2789 | <size> | 2808 | <size> |
| 2790 | <width>55</width> | 2809 | <width>68</width> |
| 2791 | <height>16777215</height> | 2810 | <height>16777215</height> |
| 2792 | </size> | 2811 | </size> |
| 2793 | </property> | 2812 | </property> |
| 2794 | <property name="styleSheet"> | 2813 | <property name="styleSheet"> |
| 2795 | <string notr="true">min-width: 55px;</string> | 2814 | <string notr="true">min-width: 68px;</string> |
| 2796 | </property> | 2815 | </property> |
| 2797 | <property name="text"> | 2816 | <property name="text"> |
| 2798 | <string>Down</string> | 2817 | <string>Down</string> |
| @@ -2851,18 +2870,18 @@ | |||
| 2851 | <widget class="QPushButton" name="buttonRStick"> | 2870 | <widget class="QPushButton" name="buttonRStick"> |
| 2852 | <property name="minimumSize"> | 2871 | <property name="minimumSize"> |
| 2853 | <size> | 2872 | <size> |
| 2854 | <width>57</width> | 2873 | <width>68</width> |
| 2855 | <height>0</height> | 2874 | <height>0</height> |
| 2856 | </size> | 2875 | </size> |
| 2857 | </property> | 2876 | </property> |
| 2858 | <property name="maximumSize"> | 2877 | <property name="maximumSize"> |
| 2859 | <size> | 2878 | <size> |
| 2860 | <width>55</width> | 2879 | <width>68</width> |
| 2861 | <height>16777215</height> | 2880 | <height>16777215</height> |
| 2862 | </size> | 2881 | </size> |
| 2863 | </property> | 2882 | </property> |
| 2864 | <property name="styleSheet"> | 2883 | <property name="styleSheet"> |
| 2865 | <string notr="true">min-width: 55px;</string> | 2884 | <string notr="true">min-width: 68px;</string> |
| 2866 | </property> | 2885 | </property> |
| 2867 | <property name="text"> | 2886 | <property name="text"> |
| 2868 | <string>Pressed</string> | 2887 | <string>Pressed</string> |
| @@ -2900,18 +2919,18 @@ | |||
| 2900 | <widget class="QPushButton" name="buttonRStickMod"> | 2919 | <widget class="QPushButton" name="buttonRStickMod"> |
| 2901 | <property name="minimumSize"> | 2920 | <property name="minimumSize"> |
| 2902 | <size> | 2921 | <size> |
| 2903 | <width>57</width> | 2922 | <width>68</width> |
| 2904 | <height>0</height> | 2923 | <height>0</height> |
| 2905 | </size> | 2924 | </size> |
| 2906 | </property> | 2925 | </property> |
| 2907 | <property name="maximumSize"> | 2926 | <property name="maximumSize"> |
| 2908 | <size> | 2927 | <size> |
| 2909 | <width>55</width> | 2928 | <width>68</width> |
| 2910 | <height>16777215</height> | 2929 | <height>16777215</height> |
| 2911 | </size> | 2930 | </size> |
| 2912 | </property> | 2931 | </property> |
| 2913 | <property name="styleSheet"> | 2932 | <property name="styleSheet"> |
| 2914 | <string notr="true">min-width: 55px;</string> | 2933 | <string notr="true">min-width: 68px;</string> |
| 2915 | </property> | 2934 | </property> |
| 2916 | <property name="text"> | 2935 | <property name="text"> |
| 2917 | <string>Modifier</string> | 2936 | <string>Modifier</string> |
| @@ -2946,13 +2965,13 @@ | |||
| 2946 | <widget class="QSpinBox" name="spinboxRStickRange"> | 2965 | <widget class="QSpinBox" name="spinboxRStickRange"> |
| 2947 | <property name="minimumSize"> | 2966 | <property name="minimumSize"> |
| 2948 | <size> | 2967 | <size> |
| 2949 | <width>55</width> | 2968 | <width>68</width> |
| 2950 | <height>21</height> | 2969 | <height>21</height> |
| 2951 | </size> | 2970 | </size> |
| 2952 | </property> | 2971 | </property> |
| 2953 | <property name="maximumSize"> | 2972 | <property name="maximumSize"> |
| 2954 | <size> | 2973 | <size> |
| 2955 | <width>55</width> | 2974 | <width>68</width> |
| 2956 | <height>16777215</height> | 2975 | <height>16777215</height> |
| 2957 | </size> | 2976 | </size> |
| 2958 | </property> | 2977 | </property> |
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp new file mode 100644 index 000000000..1f5cfa75b --- /dev/null +++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_input_profile_dialog.h" | ||
| 6 | #include "yuzu/configuration/configure_input_player.h" | ||
| 7 | #include "yuzu/configuration/configure_input_profile_dialog.h" | ||
| 8 | |||
| 9 | ConfigureInputProfileDialog::ConfigureInputProfileDialog( | ||
| 10 | QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles) | ||
| 11 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()), | ||
| 12 | profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, false)) { | ||
| 13 | ui->setupUi(this); | ||
| 14 | |||
| 15 | ui->controllerLayout->addWidget(profile_widget); | ||
| 16 | |||
| 17 | connect(ui->clear_all_button, &QPushButton::clicked, this, | ||
| 18 | [this] { profile_widget->ClearAll(); }); | ||
| 19 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | ||
| 20 | [this] { profile_widget->RestoreDefaults(); }); | ||
| 21 | |||
| 22 | RetranslateUI(); | ||
| 23 | } | ||
| 24 | |||
| 25 | ConfigureInputProfileDialog::~ConfigureInputProfileDialog() = default; | ||
| 26 | |||
| 27 | void ConfigureInputProfileDialog::changeEvent(QEvent* event) { | ||
| 28 | if (event->type() == QEvent::LanguageChange) { | ||
| 29 | RetranslateUI(); | ||
| 30 | } | ||
| 31 | |||
| 32 | QDialog::changeEvent(event); | ||
| 33 | } | ||
| 34 | |||
| 35 | void ConfigureInputProfileDialog::RetranslateUI() { | ||
| 36 | ui->retranslateUi(this); | ||
| 37 | } | ||
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.h b/src/yuzu/configuration/configure_input_profile_dialog.h new file mode 100644 index 000000000..e6386bdbb --- /dev/null +++ b/src/yuzu/configuration/configure_input_profile_dialog.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | |||
| 10 | class QPushButton; | ||
| 11 | |||
| 12 | class ConfigureInputPlayer; | ||
| 13 | |||
| 14 | class InputProfiles; | ||
| 15 | |||
| 16 | namespace InputCommon { | ||
| 17 | class InputSubsystem; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Ui { | ||
| 21 | class ConfigureInputProfileDialog; | ||
| 22 | } | ||
| 23 | |||
| 24 | class ConfigureInputProfileDialog : public QDialog { | ||
| 25 | Q_OBJECT | ||
| 26 | |||
| 27 | public: | ||
| 28 | explicit ConfigureInputProfileDialog(QWidget* parent, | ||
| 29 | InputCommon::InputSubsystem* input_subsystem, | ||
| 30 | InputProfiles* profiles); | ||
| 31 | ~ConfigureInputProfileDialog() override; | ||
| 32 | |||
| 33 | private: | ||
| 34 | void changeEvent(QEvent* event) override; | ||
| 35 | void RetranslateUI(); | ||
| 36 | |||
| 37 | std::unique_ptr<Ui::ConfigureInputProfileDialog> ui; | ||
| 38 | |||
| 39 | ConfigureInputPlayer* profile_widget; | ||
| 40 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_dialog.ui b/src/yuzu/configuration/configure_input_profile_dialog.ui index b92ddb200..726cf6905 100644 --- a/src/yuzu/configuration/configure_input_dialog.ui +++ b/src/yuzu/configuration/configure_input_profile_dialog.ui | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInputDialog</class> | 3 | <class>ConfigureInputProfileDialog</class> |
| 4 | <widget class="QDialog" name="ConfigureInputDialog"> | 4 | <widget class="QDialog" name="ConfigureInputProfileDialog"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| @@ -11,7 +11,7 @@ | |||
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Input</string> | 14 | <string>Create Input Profile</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 17 | <property name="spacing"> | 17 | <property name="spacing"> |
| @@ -30,11 +30,25 @@ | |||
| 30 | <number>9</number> | 30 | <number>9</number> |
| 31 | </property> | 31 | </property> |
| 32 | <item> | 32 | <item> |
| 33 | <layout class="QHBoxLayout" name="inputLayout"/> | 33 | <layout class="QHBoxLayout" name="controllerLayout"/> |
| 34 | </item> | 34 | </item> |
| 35 | <item> | 35 | <item> |
| 36 | <layout class="QHBoxLayout" name="horizontalLayout"> | 36 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 37 | <item> | 37 | <item> |
| 38 | <widget class="QPushButton" name="clear_all_button"> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Clear</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 46 | <property name="text"> | ||
| 47 | <string>Defaults</string> | ||
| 48 | </property> | ||
| 49 | </widget> | ||
| 50 | </item> | ||
| 51 | <item> | ||
| 38 | <widget class="QDialogButtonBox" name="buttonBox"> | 52 | <widget class="QDialogButtonBox" name="buttonBox"> |
| 39 | <property name="standardButtons"> | 53 | <property name="standardButtons"> |
| 40 | <set>QDialogButtonBox::Ok</set> | 54 | <set>QDialogButtonBox::Ok</set> |
| @@ -50,7 +64,7 @@ | |||
| 50 | <connection> | 64 | <connection> |
| 51 | <sender>buttonBox</sender> | 65 | <sender>buttonBox</sender> |
| 52 | <signal>accepted()</signal> | 66 | <signal>accepted()</signal> |
| 53 | <receiver>ConfigureInputDialog</receiver> | 67 | <receiver>ConfigureInputProfileDialog</receiver> |
| 54 | <slot>accept()</slot> | 68 | <slot>accept()</slot> |
| 55 | </connection> | 69 | </connection> |
| 56 | </connections> | 70 | </connections> |
diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index 602cf8cd8..5b78c5a4b 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui | |||
| @@ -312,16 +312,6 @@ | |||
| 312 | <signal>accepted()</signal> | 312 | <signal>accepted()</signal> |
| 313 | <receiver>ConfigureMotionTouch</receiver> | 313 | <receiver>ConfigureMotionTouch</receiver> |
| 314 | <slot>ApplyConfiguration()</slot> | 314 | <slot>ApplyConfiguration()</slot> |
| 315 | <hints> | ||
| 316 | <hint type="sourcelabel"> | ||
| 317 | <x>220</x> | ||
| 318 | <y>380</y> | ||
| 319 | </hint> | ||
| 320 | <hint type="destinationlabel"> | ||
| 321 | <x>220</x> | ||
| 322 | <y>200</y> | ||
| 323 | </hint> | ||
| 324 | </hints> | ||
| 325 | </connection> | 315 | </connection> |
| 326 | </connections> | 316 | </connections> |
| 327 | </ui> | 317 | </ui> |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui index 74552fdbd..5b99e1c37 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ b/src/yuzu/configuration/configure_mouse_advanced.ui | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | </property> | 15 | </property> |
| 16 | <property name="styleSheet"> | 16 | <property name="styleSheet"> |
| 17 | <string notr="true">QPushButton { | 17 | <string notr="true">QPushButton { |
| 18 | min-width: 55px; | 18 | min-width: 60px; |
| 19 | }</string> | 19 | }</string> |
| 20 | </property> | 20 | </property> |
| 21 | <layout class="QVBoxLayout" name="verticalLayout"> | 21 | <layout class="QVBoxLayout" name="verticalLayout"> |
| @@ -42,13 +42,13 @@ | |||
| 42 | <widget class="QPushButton" name="forward_button"> | 42 | <widget class="QPushButton" name="forward_button"> |
| 43 | <property name="minimumSize"> | 43 | <property name="minimumSize"> |
| 44 | <size> | 44 | <size> |
| 45 | <width>57</width> | 45 | <width>68</width> |
| 46 | <height>0</height> | 46 | <height>0</height> |
| 47 | </size> | 47 | </size> |
| 48 | </property> | 48 | </property> |
| 49 | <property name="maximumSize"> | 49 | <property name="maximumSize"> |
| 50 | <size> | 50 | <size> |
| 51 | <width>16777215</width> | 51 | <width>68</width> |
| 52 | <height>16777215</height> | 52 | <height>16777215</height> |
| 53 | </size> | 53 | </size> |
| 54 | </property> | 54 | </property> |
| @@ -82,7 +82,7 @@ | |||
| 82 | <widget class="QPushButton" name="back_button"> | 82 | <widget class="QPushButton" name="back_button"> |
| 83 | <property name="minimumSize"> | 83 | <property name="minimumSize"> |
| 84 | <size> | 84 | <size> |
| 85 | <width>57</width> | 85 | <width>68</width> |
| 86 | <height>0</height> | 86 | <height>0</height> |
| 87 | </size> | 87 | </size> |
| 88 | </property> | 88 | </property> |
| @@ -110,7 +110,7 @@ | |||
| 110 | <widget class="QPushButton" name="left_button"> | 110 | <widget class="QPushButton" name="left_button"> |
| 111 | <property name="minimumSize"> | 111 | <property name="minimumSize"> |
| 112 | <size> | 112 | <size> |
| 113 | <width>57</width> | 113 | <width>68</width> |
| 114 | <height>0</height> | 114 | <height>0</height> |
| 115 | </size> | 115 | </size> |
| 116 | </property> | 116 | </property> |
| @@ -138,13 +138,13 @@ | |||
| 138 | <widget class="QPushButton" name="middle_button"> | 138 | <widget class="QPushButton" name="middle_button"> |
| 139 | <property name="minimumSize"> | 139 | <property name="minimumSize"> |
| 140 | <size> | 140 | <size> |
| 141 | <width>57</width> | 141 | <width>68</width> |
| 142 | <height>0</height> | 142 | <height>0</height> |
| 143 | </size> | 143 | </size> |
| 144 | </property> | 144 | </property> |
| 145 | <property name="maximumSize"> | 145 | <property name="maximumSize"> |
| 146 | <size> | 146 | <size> |
| 147 | <width>16777215</width> | 147 | <width>68</width> |
| 148 | <height>16777215</height> | 148 | <height>16777215</height> |
| 149 | </size> | 149 | </size> |
| 150 | </property> | 150 | </property> |
| @@ -204,13 +204,13 @@ | |||
| 204 | <widget class="QPushButton" name="right_button"> | 204 | <widget class="QPushButton" name="right_button"> |
| 205 | <property name="minimumSize"> | 205 | <property name="minimumSize"> |
| 206 | <size> | 206 | <size> |
| 207 | <width>57</width> | 207 | <width>68</width> |
| 208 | <height>0</height> | 208 | <height>0</height> |
| 209 | </size> | 209 | </size> |
| 210 | </property> | 210 | </property> |
| 211 | <property name="maximumSize"> | 211 | <property name="maximumSize"> |
| 212 | <size> | 212 | <size> |
| 213 | <width>16777215</width> | 213 | <width>68</width> |
| 214 | <height>16777215</height> | 214 | <height>16777215</height> |
| 215 | </size> | 215 | </size> |
| 216 | </property> | 216 | </property> |
| @@ -256,13 +256,13 @@ | |||
| 256 | <widget class="QPushButton" name="buttonClearAll"> | 256 | <widget class="QPushButton" name="buttonClearAll"> |
| 257 | <property name="minimumSize"> | 257 | <property name="minimumSize"> |
| 258 | <size> | 258 | <size> |
| 259 | <width>57</width> | 259 | <width>68</width> |
| 260 | <height>0</height> | 260 | <height>0</height> |
| 261 | </size> | 261 | </size> |
| 262 | </property> | 262 | </property> |
| 263 | <property name="maximumSize"> | 263 | <property name="maximumSize"> |
| 264 | <size> | 264 | <size> |
| 265 | <width>16777215</width> | 265 | <width>68</width> |
| 266 | <height>16777215</height> | 266 | <height>16777215</height> |
| 267 | </size> | 267 | </size> |
| 268 | </property> | 268 | </property> |
| @@ -275,13 +275,13 @@ | |||
| 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> | 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> |
| 276 | <property name="minimumSize"> | 276 | <property name="minimumSize"> |
| 277 | <size> | 277 | <size> |
| 278 | <width>57</width> | 278 | <width>68</width> |
| 279 | <height>0</height> | 279 | <height>0</height> |
| 280 | </size> | 280 | </size> |
| 281 | </property> | 281 | </property> |
| 282 | <property name="maximumSize"> | 282 | <property name="maximumSize"> |
| 283 | <size> | 283 | <size> |
| 284 | <width>16777215</width> | 284 | <width>68</width> |
| 285 | <height>16777215</height> | 285 | <height>16777215</height> |
| 286 | </size> | 286 | </size> |
| 287 | </property> | 287 | </property> |
| @@ -324,32 +324,12 @@ | |||
| 324 | <signal>accepted()</signal> | 324 | <signal>accepted()</signal> |
| 325 | <receiver>ConfigureMouseAdvanced</receiver> | 325 | <receiver>ConfigureMouseAdvanced</receiver> |
| 326 | <slot>accept()</slot> | 326 | <slot>accept()</slot> |
| 327 | <hints> | ||
| 328 | <hint type="sourcelabel"> | ||
| 329 | <x>124</x> | ||
| 330 | <y>266</y> | ||
| 331 | </hint> | ||
| 332 | <hint type="destinationlabel"> | ||
| 333 | <x>124</x> | ||
| 334 | <y>143</y> | ||
| 335 | </hint> | ||
| 336 | </hints> | ||
| 337 | </connection> | 327 | </connection> |
| 338 | <connection> | 328 | <connection> |
| 339 | <sender>buttonBox</sender> | 329 | <sender>buttonBox</sender> |
| 340 | <signal>rejected()</signal> | 330 | <signal>rejected()</signal> |
| 341 | <receiver>ConfigureMouseAdvanced</receiver> | 331 | <receiver>ConfigureMouseAdvanced</receiver> |
| 342 | <slot>reject()</slot> | 332 | <slot>reject()</slot> |
| 343 | <hints> | ||
| 344 | <hint type="sourcelabel"> | ||
| 345 | <x>124</x> | ||
| 346 | <y>266</y> | ||
| 347 | </hint> | ||
| 348 | <hint type="destinationlabel"> | ||
| 349 | <x>124</x> | ||
| 350 | <y>143</y> | ||
| 351 | </hint> | ||
| 352 | </hints> | ||
| 353 | </connection> | 333 | </connection> |
| 354 | </connections> | 334 | </connections> |
| 355 | </ui> | 335 | </ui> |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 002db3f93..8eac3bd9d 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include "common/common_paths.h" | 17 | #include "common/common_paths.h" |
| 18 | #include "common/file_util.h" | 18 | #include "common/file_util.h" |
| 19 | #include "core/core.h" | ||
| 19 | #include "core/file_sys/control_metadata.h" | 20 | #include "core/file_sys/control_metadata.h" |
| 20 | #include "core/file_sys/patch_manager.h" | 21 | #include "core/file_sys/patch_manager.h" |
| 21 | #include "core/file_sys/xts_archive.h" | 22 | #include "core/file_sys/xts_archive.h" |
| @@ -29,7 +30,8 @@ | |||
| 29 | 30 | ||
| 30 | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id) | 31 | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id) |
| 31 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) { | 32 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) { |
| 32 | game_config = std::make_unique<Config>(fmt::format("{:016X}.ini", title_id), false); | 33 | game_config = std::make_unique<Config>(fmt::format("{:016X}", title_id), |
| 34 | Config::ConfigType::PerGameConfig); | ||
| 33 | 35 | ||
| 34 | Settings::SetConfiguringGlobal(false); | 36 | Settings::SetConfiguringGlobal(false); |
| 35 | 37 | ||
| @@ -88,9 +90,11 @@ void ConfigurePerGame::LoadConfiguration() { | |||
| 88 | ui->display_title_id->setText( | 90 | ui->display_title_id->setText( |
| 89 | QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); | 91 | QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); |
| 90 | 92 | ||
| 91 | FileSys::PatchManager pm{title_id}; | 93 | auto& system = Core::System::GetInstance(); |
| 94 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | ||
| 95 | system.GetContentProvider()}; | ||
| 92 | const auto control = pm.GetControlMetadata(); | 96 | const auto control = pm.GetControlMetadata(); |
| 93 | const auto loader = Loader::GetLoader(file); | 97 | const auto loader = Loader::GetLoader(system, file); |
| 94 | 98 | ||
| 95 | if (control.first != nullptr) { | 99 | if (control.first != nullptr) { |
| 96 | ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); | 100 | ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); |
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index d2057c4ab..25975b3b9 100644 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -319,32 +319,12 @@ | |||
| 319 | <signal>accepted()</signal> | 319 | <signal>accepted()</signal> |
| 320 | <receiver>ConfigurePerGame</receiver> | 320 | <receiver>ConfigurePerGame</receiver> |
| 321 | <slot>accept()</slot> | 321 | <slot>accept()</slot> |
| 322 | <hints> | ||
| 323 | <hint type="sourcelabel"> | ||
| 324 | <x>248</x> | ||
| 325 | <y>254</y> | ||
| 326 | </hint> | ||
| 327 | <hint type="destinationlabel"> | ||
| 328 | <x>157</x> | ||
| 329 | <y>274</y> | ||
| 330 | </hint> | ||
| 331 | </hints> | ||
| 332 | </connection> | 322 | </connection> |
| 333 | <connection> | 323 | <connection> |
| 334 | <sender>buttonBox</sender> | 324 | <sender>buttonBox</sender> |
| 335 | <signal>rejected()</signal> | 325 | <signal>rejected()</signal> |
| 336 | <receiver>ConfigurePerGame</receiver> | 326 | <receiver>ConfigurePerGame</receiver> |
| 337 | <slot>reject()</slot> | 327 | <slot>reject()</slot> |
| 338 | <hints> | ||
| 339 | <hint type="sourcelabel"> | ||
| 340 | <x>316</x> | ||
| 341 | <y>260</y> | ||
| 342 | </hint> | ||
| 343 | <hint type="destinationlabel"> | ||
| 344 | <x>286</x> | ||
| 345 | <y>274</y> | ||
| 346 | </hint> | ||
| 347 | </hints> | ||
| 348 | </connection> | 328 | </connection> |
| 349 | </connections> | 329 | </connections> |
| 350 | </ui> | 330 | </ui> |
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 793fd8975..cdeeec01c 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp | |||
| @@ -112,8 +112,10 @@ void ConfigurePerGameAddons::LoadConfiguration() { | |||
| 112 | return; | 112 | return; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | FileSys::PatchManager pm{title_id}; | 115 | auto& system = Core::System::GetInstance(); |
| 116 | const auto loader = Loader::GetLoader(file); | 116 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 117 | system.GetContentProvider()}; | ||
| 118 | const auto loader = Loader::GetLoader(system, file); | ||
| 117 | 119 | ||
| 118 | FileSys::VirtualFile update_raw; | 120 | FileSys::VirtualFile update_raw; |
| 119 | loader->ReadUpdateRaw(update_raw); | 121 | loader->ReadUpdateRaw(update_raw); |
diff --git a/src/yuzu/configuration/configure_touch_from_button.ui b/src/yuzu/configuration/configure_touch_from_button.ui index f581e27e0..757219d54 100644 --- a/src/yuzu/configuration/configure_touch_from_button.ui +++ b/src/yuzu/configuration/configure_touch_from_button.ui | |||
| @@ -216,16 +216,6 @@ Drag points to change position, or double-click table cells to edit values.</str | |||
| 216 | <signal>rejected()</signal> | 216 | <signal>rejected()</signal> |
| 217 | <receiver>ConfigureTouchFromButton</receiver> | 217 | <receiver>ConfigureTouchFromButton</receiver> |
| 218 | <slot>reject()</slot> | 218 | <slot>reject()</slot> |
| 219 | <hints> | ||
| 220 | <hint type="sourcelabel"> | ||
| 221 | <x>249</x> | ||
| 222 | <y>428</y> | ||
| 223 | </hint> | ||
| 224 | <hint type="destinationlabel"> | ||
| 225 | <x>249</x> | ||
| 226 | <y>224</y> | ||
| 227 | </hint> | ||
| 228 | </hints> | ||
| 229 | </connection> | 219 | </connection> |
| 230 | </connections> | 220 | </connections> |
| 231 | </ui> | 221 | </ui> |
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.ui b/src/yuzu/configuration/configure_touchscreen_advanced.ui index 1171c2dd1..30ceccddb 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.ui +++ b/src/yuzu/configuration/configure_touchscreen_advanced.ui | |||
| @@ -168,32 +168,12 @@ | |||
| 168 | <signal>accepted()</signal> | 168 | <signal>accepted()</signal> |
| 169 | <receiver>ConfigureTouchscreenAdvanced</receiver> | 169 | <receiver>ConfigureTouchscreenAdvanced</receiver> |
| 170 | <slot>accept()</slot> | 170 | <slot>accept()</slot> |
| 171 | <hints> | ||
| 172 | <hint type="sourcelabel"> | ||
| 173 | <x>140</x> | ||
| 174 | <y>318</y> | ||
| 175 | </hint> | ||
| 176 | <hint type="destinationlabel"> | ||
| 177 | <x>140</x> | ||
| 178 | <y>169</y> | ||
| 179 | </hint> | ||
| 180 | </hints> | ||
| 181 | </connection> | 171 | </connection> |
| 182 | <connection> | 172 | <connection> |
| 183 | <sender>buttonBox</sender> | 173 | <sender>buttonBox</sender> |
| 184 | <signal>rejected()</signal> | 174 | <signal>rejected()</signal> |
| 185 | <receiver>ConfigureTouchscreenAdvanced</receiver> | 175 | <receiver>ConfigureTouchscreenAdvanced</receiver> |
| 186 | <slot>reject()</slot> | 176 | <slot>reject()</slot> |
| 187 | <hints> | 177 | </connection> |
| 188 | <hint type="sourcelabel"> | ||
| 189 | <x>140</x> | ||
| 190 | <y>318</y> | ||
| 191 | </hint> | ||
| 192 | <hint type="destinationlabel"> | ||
| 193 | <x>140</x> | ||
| 194 | <y>169</y> | ||
| 195 | </hint> | ||
| 196 | </hints> | ||
| 197 | </connection> | ||
| 198 | </connections> | 178 | </connections> |
| 199 | </ui> | 179 | </ui> |
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp new file mode 100644 index 000000000..7dcb2c5b9 --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.cpp | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <unordered_map> | ||
| 7 | |||
| 8 | #include <fmt/format.h> | ||
| 9 | |||
| 10 | #include "common/param_package.h" | ||
| 11 | #include "core/settings.h" | ||
| 12 | #include "ui_configure_vibration.h" | ||
| 13 | #include "yuzu/configuration/configure_vibration.h" | ||
| 14 | |||
| 15 | ConfigureVibration::ConfigureVibration(QWidget* parent) | ||
| 16 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) { | ||
| 17 | ui->setupUi(this); | ||
| 18 | |||
| 19 | vibration_groupboxes = { | ||
| 20 | ui->vibrationGroupPlayer1, ui->vibrationGroupPlayer2, ui->vibrationGroupPlayer3, | ||
| 21 | ui->vibrationGroupPlayer4, ui->vibrationGroupPlayer5, ui->vibrationGroupPlayer6, | ||
| 22 | ui->vibrationGroupPlayer7, ui->vibrationGroupPlayer8, | ||
| 23 | }; | ||
| 24 | |||
| 25 | vibration_spinboxes = { | ||
| 26 | ui->vibrationSpinPlayer1, ui->vibrationSpinPlayer2, ui->vibrationSpinPlayer3, | ||
| 27 | ui->vibrationSpinPlayer4, ui->vibrationSpinPlayer5, ui->vibrationSpinPlayer6, | ||
| 28 | ui->vibrationSpinPlayer7, ui->vibrationSpinPlayer8, | ||
| 29 | }; | ||
| 30 | |||
| 31 | const auto& players = Settings::values.players.GetValue(); | ||
| 32 | |||
| 33 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | ||
| 34 | vibration_groupboxes[i]->setChecked(players[i].vibration_enabled); | ||
| 35 | vibration_spinboxes[i]->setValue(players[i].vibration_strength); | ||
| 36 | } | ||
| 37 | |||
| 38 | ui->checkBoxAccurateVibration->setChecked( | ||
| 39 | Settings::values.enable_accurate_vibrations.GetValue()); | ||
| 40 | |||
| 41 | if (!Settings::IsConfiguringGlobal()) { | ||
| 42 | ui->checkBoxAccurateVibration->setDisabled(true); | ||
| 43 | } | ||
| 44 | |||
| 45 | RetranslateUI(); | ||
| 46 | } | ||
| 47 | |||
| 48 | ConfigureVibration::~ConfigureVibration() = default; | ||
| 49 | |||
| 50 | void ConfigureVibration::ApplyConfiguration() { | ||
| 51 | auto& players = Settings::values.players.GetValue(); | ||
| 52 | |||
| 53 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | ||
| 54 | players[i].vibration_enabled = vibration_groupboxes[i]->isChecked(); | ||
| 55 | players[i].vibration_strength = vibration_spinboxes[i]->value(); | ||
| 56 | } | ||
| 57 | |||
| 58 | Settings::values.enable_accurate_vibrations.SetValue( | ||
| 59 | ui->checkBoxAccurateVibration->isChecked()); | ||
| 60 | } | ||
| 61 | |||
| 62 | void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { | ||
| 63 | using namespace Settings::NativeButton; | ||
| 64 | static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{ | ||
| 65 | {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons | ||
| 66 | {A, B, X, Y, R, ZR}, // Right Buttons | ||
| 67 | }}; | ||
| 68 | |||
| 69 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 70 | |||
| 71 | for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { | ||
| 72 | std::unordered_map<std::string, int> params_count; | ||
| 73 | |||
| 74 | for (const auto button_index : buttons[device_idx]) { | ||
| 75 | const auto& player_button = player.buttons[button_index]; | ||
| 76 | |||
| 77 | if (params_count.find(player_button) != params_count.end()) { | ||
| 78 | ++params_count[player_button]; | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | |||
| 82 | params_count.insert_or_assign(player_button, 1); | ||
| 83 | } | ||
| 84 | |||
| 85 | const auto it = std::max_element( | ||
| 86 | params_count.begin(), params_count.end(), | ||
| 87 | [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); | ||
| 88 | |||
| 89 | auto& vibration_param_str = player.vibrations[device_idx]; | ||
| 90 | vibration_param_str.clear(); | ||
| 91 | |||
| 92 | if (it->first.empty()) { | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | |||
| 96 | const auto param = Common::ParamPackage(it->first); | ||
| 97 | |||
| 98 | const auto engine = param.Get("engine", ""); | ||
| 99 | const auto guid = param.Get("guid", ""); | ||
| 100 | const auto port = param.Get("port", ""); | ||
| 101 | |||
| 102 | if (engine.empty() || engine == "keyboard" || engine == "mouse") { | ||
| 103 | continue; | ||
| 104 | } | ||
| 105 | |||
| 106 | vibration_param_str += fmt::format("engine:{}", engine); | ||
| 107 | |||
| 108 | if (!port.empty()) { | ||
| 109 | vibration_param_str += fmt::format(",port:{}", port); | ||
| 110 | } | ||
| 111 | if (!guid.empty()) { | ||
| 112 | vibration_param_str += fmt::format(",guid:{}", guid); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | if (player.vibrations[0] != player.vibrations[1]) { | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | if (!player.vibrations[0].empty() && | ||
| 121 | player.controller_type != Settings::ControllerType::RightJoycon) { | ||
| 122 | player.vibrations[1].clear(); | ||
| 123 | } else if (!player.vibrations[1].empty() && | ||
| 124 | player.controller_type == Settings::ControllerType::RightJoycon) { | ||
| 125 | player.vibrations[0].clear(); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | void ConfigureVibration::SetAllVibrationDevices() { | ||
| 130 | // Set vibration devices for all player indices including handheld | ||
| 131 | for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { | ||
| 132 | SetVibrationDevices(player_idx); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | void ConfigureVibration::changeEvent(QEvent* event) { | ||
| 137 | if (event->type() == QEvent::LanguageChange) { | ||
| 138 | RetranslateUI(); | ||
| 139 | } | ||
| 140 | |||
| 141 | QDialog::changeEvent(event); | ||
| 142 | } | ||
| 143 | |||
| 144 | void ConfigureVibration::RetranslateUI() { | ||
| 145 | ui->retranslateUi(this); | ||
| 146 | } | ||
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h new file mode 100644 index 000000000..07411a86f --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <memory> | ||
| 9 | #include <QDialog> | ||
| 10 | |||
| 11 | class QGroupBox; | ||
| 12 | class QSpinBox; | ||
| 13 | |||
| 14 | namespace Ui { | ||
| 15 | class ConfigureVibration; | ||
| 16 | } | ||
| 17 | |||
| 18 | class ConfigureVibration : public QDialog { | ||
| 19 | Q_OBJECT | ||
| 20 | |||
| 21 | public: | ||
| 22 | explicit ConfigureVibration(QWidget* parent); | ||
| 23 | ~ConfigureVibration() override; | ||
| 24 | |||
| 25 | void ApplyConfiguration(); | ||
| 26 | |||
| 27 | static void SetVibrationDevices(std::size_t player_index); | ||
| 28 | static void SetAllVibrationDevices(); | ||
| 29 | |||
| 30 | private: | ||
| 31 | void changeEvent(QEvent* event) override; | ||
| 32 | void RetranslateUI(); | ||
| 33 | |||
| 34 | std::unique_ptr<Ui::ConfigureVibration> ui; | ||
| 35 | |||
| 36 | static constexpr std::size_t NUM_PLAYERS = 8; | ||
| 37 | |||
| 38 | // Groupboxes encapsulating the vibration strength spinbox. | ||
| 39 | std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes; | ||
| 40 | |||
| 41 | // Spinboxes representing the vibration strength percentage. | ||
| 42 | std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes; | ||
| 43 | }; | ||
diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui new file mode 100644 index 000000000..efdf317a9 --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.ui | |||
| @@ -0,0 +1,546 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureVibration</class> | ||
| 4 | <widget class="QDialog" name="ConfigureVibration"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>364</width> | ||
| 10 | <height>242</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Vibration</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout"> | ||
| 20 | <item> | ||
| 21 | <widget class="QGroupBox" name="vibrationStrengthGroup"> | ||
| 22 | <property name="title"> | ||
| 23 | <string>Vibration</string> | ||
| 24 | </property> | ||
| 25 | <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0"> | ||
| 26 | <property name="leftMargin"> | ||
| 27 | <number>9</number> | ||
| 28 | </property> | ||
| 29 | <property name="topMargin"> | ||
| 30 | <number>9</number> | ||
| 31 | </property> | ||
| 32 | <property name="rightMargin"> | ||
| 33 | <number>9</number> | ||
| 34 | </property> | ||
| 35 | <property name="bottomMargin"> | ||
| 36 | <number>9</number> | ||
| 37 | </property> | ||
| 38 | <item> | ||
| 39 | <widget class="QWidget" name="player14Widget" native="true"> | ||
| 40 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||
| 41 | <property name="leftMargin"> | ||
| 42 | <number>0</number> | ||
| 43 | </property> | ||
| 44 | <property name="topMargin"> | ||
| 45 | <number>0</number> | ||
| 46 | </property> | ||
| 47 | <property name="rightMargin"> | ||
| 48 | <number>0</number> | ||
| 49 | </property> | ||
| 50 | <property name="bottomMargin"> | ||
| 51 | <number>0</number> | ||
| 52 | </property> | ||
| 53 | <item> | ||
| 54 | <widget class="QGroupBox" name="vibrationGroupPlayer1"> | ||
| 55 | <property name="title"> | ||
| 56 | <string>Player 1</string> | ||
| 57 | </property> | ||
| 58 | <property name="checkable"> | ||
| 59 | <bool>true</bool> | ||
| 60 | </property> | ||
| 61 | <layout class="QHBoxLayout" name="horizontalLayout_8"> | ||
| 62 | <property name="leftMargin"> | ||
| 63 | <number>3</number> | ||
| 64 | </property> | ||
| 65 | <property name="topMargin"> | ||
| 66 | <number>3</number> | ||
| 67 | </property> | ||
| 68 | <property name="rightMargin"> | ||
| 69 | <number>3</number> | ||
| 70 | </property> | ||
| 71 | <property name="bottomMargin"> | ||
| 72 | <number>3</number> | ||
| 73 | </property> | ||
| 74 | <item> | ||
| 75 | <widget class="QSpinBox" name="vibrationSpinPlayer1"> | ||
| 76 | <property name="minimumSize"> | ||
| 77 | <size> | ||
| 78 | <width>68</width> | ||
| 79 | <height>21</height> | ||
| 80 | </size> | ||
| 81 | </property> | ||
| 82 | <property name="maximumSize"> | ||
| 83 | <size> | ||
| 84 | <width>68</width> | ||
| 85 | <height>16777215</height> | ||
| 86 | </size> | ||
| 87 | </property> | ||
| 88 | <property name="suffix"> | ||
| 89 | <string>%</string> | ||
| 90 | </property> | ||
| 91 | <property name="minimum"> | ||
| 92 | <number>1</number> | ||
| 93 | </property> | ||
| 94 | <property name="maximum"> | ||
| 95 | <number>150</number> | ||
| 96 | </property> | ||
| 97 | <property name="value"> | ||
| 98 | <number>100</number> | ||
| 99 | </property> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | </layout> | ||
| 103 | </widget> | ||
| 104 | </item> | ||
| 105 | <item> | ||
| 106 | <widget class="QGroupBox" name="vibrationGroupPlayer2"> | ||
| 107 | <property name="title"> | ||
| 108 | <string>Player 2</string> | ||
| 109 | </property> | ||
| 110 | <property name="checkable"> | ||
| 111 | <bool>true</bool> | ||
| 112 | </property> | ||
| 113 | <layout class="QHBoxLayout" name="horizontalLayout_9"> | ||
| 114 | <property name="leftMargin"> | ||
| 115 | <number>3</number> | ||
| 116 | </property> | ||
| 117 | <property name="topMargin"> | ||
| 118 | <number>3</number> | ||
| 119 | </property> | ||
| 120 | <property name="rightMargin"> | ||
| 121 | <number>3</number> | ||
| 122 | </property> | ||
| 123 | <property name="bottomMargin"> | ||
| 124 | <number>3</number> | ||
| 125 | </property> | ||
| 126 | <item> | ||
| 127 | <widget class="QSpinBox" name="vibrationSpinPlayer2"> | ||
| 128 | <property name="minimumSize"> | ||
| 129 | <size> | ||
| 130 | <width>68</width> | ||
| 131 | <height>21</height> | ||
| 132 | </size> | ||
| 133 | </property> | ||
| 134 | <property name="maximumSize"> | ||
| 135 | <size> | ||
| 136 | <width>68</width> | ||
| 137 | <height>16777215</height> | ||
| 138 | </size> | ||
| 139 | </property> | ||
| 140 | <property name="suffix"> | ||
| 141 | <string>%</string> | ||
| 142 | </property> | ||
| 143 | <property name="minimum"> | ||
| 144 | <number>1</number> | ||
| 145 | </property> | ||
| 146 | <property name="maximum"> | ||
| 147 | <number>150</number> | ||
| 148 | </property> | ||
| 149 | <property name="value"> | ||
| 150 | <number>100</number> | ||
| 151 | </property> | ||
| 152 | </widget> | ||
| 153 | </item> | ||
| 154 | </layout> | ||
| 155 | </widget> | ||
| 156 | </item> | ||
| 157 | <item> | ||
| 158 | <widget class="QGroupBox" name="vibrationGroupPlayer3"> | ||
| 159 | <property name="title"> | ||
| 160 | <string>Player 3</string> | ||
| 161 | </property> | ||
| 162 | <property name="checkable"> | ||
| 163 | <bool>true</bool> | ||
| 164 | </property> | ||
| 165 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 166 | <property name="leftMargin"> | ||
| 167 | <number>3</number> | ||
| 168 | </property> | ||
| 169 | <property name="topMargin"> | ||
| 170 | <number>3</number> | ||
| 171 | </property> | ||
| 172 | <property name="rightMargin"> | ||
| 173 | <number>3</number> | ||
| 174 | </property> | ||
| 175 | <property name="bottomMargin"> | ||
| 176 | <number>3</number> | ||
| 177 | </property> | ||
| 178 | <item> | ||
| 179 | <widget class="QSpinBox" name="vibrationSpinPlayer3"> | ||
| 180 | <property name="minimumSize"> | ||
| 181 | <size> | ||
| 182 | <width>68</width> | ||
| 183 | <height>21</height> | ||
| 184 | </size> | ||
| 185 | </property> | ||
| 186 | <property name="maximumSize"> | ||
| 187 | <size> | ||
| 188 | <width>68</width> | ||
| 189 | <height>16777215</height> | ||
| 190 | </size> | ||
| 191 | </property> | ||
| 192 | <property name="suffix"> | ||
| 193 | <string>%</string> | ||
| 194 | </property> | ||
| 195 | <property name="minimum"> | ||
| 196 | <number>1</number> | ||
| 197 | </property> | ||
| 198 | <property name="maximum"> | ||
| 199 | <number>150</number> | ||
| 200 | </property> | ||
| 201 | <property name="value"> | ||
| 202 | <number>100</number> | ||
| 203 | </property> | ||
| 204 | </widget> | ||
| 205 | </item> | ||
| 206 | </layout> | ||
| 207 | </widget> | ||
| 208 | </item> | ||
| 209 | <item> | ||
| 210 | <widget class="QGroupBox" name="vibrationGroupPlayer4"> | ||
| 211 | <property name="title"> | ||
| 212 | <string>Player 4</string> | ||
| 213 | </property> | ||
| 214 | <property name="checkable"> | ||
| 215 | <bool>true</bool> | ||
| 216 | </property> | ||
| 217 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 218 | <property name="leftMargin"> | ||
| 219 | <number>3</number> | ||
| 220 | </property> | ||
| 221 | <property name="topMargin"> | ||
| 222 | <number>3</number> | ||
| 223 | </property> | ||
| 224 | <property name="rightMargin"> | ||
| 225 | <number>3</number> | ||
| 226 | </property> | ||
| 227 | <property name="bottomMargin"> | ||
| 228 | <number>3</number> | ||
| 229 | </property> | ||
| 230 | <item> | ||
| 231 | <widget class="QSpinBox" name="vibrationSpinPlayer4"> | ||
| 232 | <property name="minimumSize"> | ||
| 233 | <size> | ||
| 234 | <width>68</width> | ||
| 235 | <height>21</height> | ||
| 236 | </size> | ||
| 237 | </property> | ||
| 238 | <property name="maximumSize"> | ||
| 239 | <size> | ||
| 240 | <width>68</width> | ||
| 241 | <height>16777215</height> | ||
| 242 | </size> | ||
| 243 | </property> | ||
| 244 | <property name="suffix"> | ||
| 245 | <string>%</string> | ||
| 246 | </property> | ||
| 247 | <property name="minimum"> | ||
| 248 | <number>1</number> | ||
| 249 | </property> | ||
| 250 | <property name="maximum"> | ||
| 251 | <number>150</number> | ||
| 252 | </property> | ||
| 253 | <property name="value"> | ||
| 254 | <number>100</number> | ||
| 255 | </property> | ||
| 256 | </widget> | ||
| 257 | </item> | ||
| 258 | </layout> | ||
| 259 | </widget> | ||
| 260 | </item> | ||
| 261 | </layout> | ||
| 262 | </widget> | ||
| 263 | </item> | ||
| 264 | <item> | ||
| 265 | <widget class="QWidget" name="player58Widget" native="true"> | ||
| 266 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||
| 267 | <property name="leftMargin"> | ||
| 268 | <number>0</number> | ||
| 269 | </property> | ||
| 270 | <property name="topMargin"> | ||
| 271 | <number>0</number> | ||
| 272 | </property> | ||
| 273 | <property name="rightMargin"> | ||
| 274 | <number>0</number> | ||
| 275 | </property> | ||
| 276 | <property name="bottomMargin"> | ||
| 277 | <number>0</number> | ||
| 278 | </property> | ||
| 279 | <item> | ||
| 280 | <widget class="QGroupBox" name="vibrationGroupPlayer7"> | ||
| 281 | <property name="title"> | ||
| 282 | <string>Player 5</string> | ||
| 283 | </property> | ||
| 284 | <property name="checkable"> | ||
| 285 | <bool>true</bool> | ||
| 286 | </property> | ||
| 287 | <layout class="QHBoxLayout" name="horizontalLayout_14"> | ||
| 288 | <property name="leftMargin"> | ||
| 289 | <number>3</number> | ||
| 290 | </property> | ||
| 291 | <property name="topMargin"> | ||
| 292 | <number>3</number> | ||
| 293 | </property> | ||
| 294 | <property name="rightMargin"> | ||
| 295 | <number>3</number> | ||
| 296 | </property> | ||
| 297 | <property name="bottomMargin"> | ||
| 298 | <number>3</number> | ||
| 299 | </property> | ||
| 300 | <item> | ||
| 301 | <widget class="QSpinBox" name="vibrationSpinPlayer7"> | ||
| 302 | <property name="minimumSize"> | ||
| 303 | <size> | ||
| 304 | <width>68</width> | ||
| 305 | <height>21</height> | ||
| 306 | </size> | ||
| 307 | </property> | ||
| 308 | <property name="maximumSize"> | ||
| 309 | <size> | ||
| 310 | <width>68</width> | ||
| 311 | <height>16777215</height> | ||
| 312 | </size> | ||
| 313 | </property> | ||
| 314 | <property name="suffix"> | ||
| 315 | <string>%</string> | ||
| 316 | </property> | ||
| 317 | <property name="minimum"> | ||
| 318 | <number>1</number> | ||
| 319 | </property> | ||
| 320 | <property name="maximum"> | ||
| 321 | <number>150</number> | ||
| 322 | </property> | ||
| 323 | <property name="value"> | ||
| 324 | <number>100</number> | ||
| 325 | </property> | ||
| 326 | </widget> | ||
| 327 | </item> | ||
| 328 | </layout> | ||
| 329 | </widget> | ||
| 330 | </item> | ||
| 331 | <item> | ||
| 332 | <widget class="QGroupBox" name="vibrationGroupPlayer8"> | ||
| 333 | <property name="title"> | ||
| 334 | <string>Player 6</string> | ||
| 335 | </property> | ||
| 336 | <property name="checkable"> | ||
| 337 | <bool>true</bool> | ||
| 338 | </property> | ||
| 339 | <layout class="QHBoxLayout" name="horizontalLayout_15"> | ||
| 340 | <property name="leftMargin"> | ||
| 341 | <number>3</number> | ||
| 342 | </property> | ||
| 343 | <property name="topMargin"> | ||
| 344 | <number>3</number> | ||
| 345 | </property> | ||
| 346 | <property name="rightMargin"> | ||
| 347 | <number>3</number> | ||
| 348 | </property> | ||
| 349 | <property name="bottomMargin"> | ||
| 350 | <number>3</number> | ||
| 351 | </property> | ||
| 352 | <item> | ||
| 353 | <widget class="QSpinBox" name="vibrationSpinPlayer8"> | ||
| 354 | <property name="minimumSize"> | ||
| 355 | <size> | ||
| 356 | <width>68</width> | ||
| 357 | <height>21</height> | ||
| 358 | </size> | ||
| 359 | </property> | ||
| 360 | <property name="maximumSize"> | ||
| 361 | <size> | ||
| 362 | <width>68</width> | ||
| 363 | <height>16777215</height> | ||
| 364 | </size> | ||
| 365 | </property> | ||
| 366 | <property name="suffix"> | ||
| 367 | <string>%</string> | ||
| 368 | </property> | ||
| 369 | <property name="minimum"> | ||
| 370 | <number>1</number> | ||
| 371 | </property> | ||
| 372 | <property name="maximum"> | ||
| 373 | <number>150</number> | ||
| 374 | </property> | ||
| 375 | <property name="value"> | ||
| 376 | <number>100</number> | ||
| 377 | </property> | ||
| 378 | </widget> | ||
| 379 | </item> | ||
| 380 | </layout> | ||
| 381 | </widget> | ||
| 382 | </item> | ||
| 383 | <item> | ||
| 384 | <widget class="QGroupBox" name="vibrationGroupPlayer5"> | ||
| 385 | <property name="title"> | ||
| 386 | <string>Player 7</string> | ||
| 387 | </property> | ||
| 388 | <property name="checkable"> | ||
| 389 | <bool>true</bool> | ||
| 390 | </property> | ||
| 391 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | ||
| 392 | <property name="leftMargin"> | ||
| 393 | <number>3</number> | ||
| 394 | </property> | ||
| 395 | <property name="topMargin"> | ||
| 396 | <number>3</number> | ||
| 397 | </property> | ||
| 398 | <property name="rightMargin"> | ||
| 399 | <number>3</number> | ||
| 400 | </property> | ||
| 401 | <property name="bottomMargin"> | ||
| 402 | <number>3</number> | ||
| 403 | </property> | ||
| 404 | <item> | ||
| 405 | <widget class="QSpinBox" name="vibrationSpinPlayer5"> | ||
| 406 | <property name="minimumSize"> | ||
| 407 | <size> | ||
| 408 | <width>68</width> | ||
| 409 | <height>21</height> | ||
| 410 | </size> | ||
| 411 | </property> | ||
| 412 | <property name="maximumSize"> | ||
| 413 | <size> | ||
| 414 | <width>68</width> | ||
| 415 | <height>16777215</height> | ||
| 416 | </size> | ||
| 417 | </property> | ||
| 418 | <property name="suffix"> | ||
| 419 | <string>%</string> | ||
| 420 | </property> | ||
| 421 | <property name="minimum"> | ||
| 422 | <number>1</number> | ||
| 423 | </property> | ||
| 424 | <property name="maximum"> | ||
| 425 | <number>150</number> | ||
| 426 | </property> | ||
| 427 | <property name="value"> | ||
| 428 | <number>100</number> | ||
| 429 | </property> | ||
| 430 | </widget> | ||
| 431 | </item> | ||
| 432 | </layout> | ||
| 433 | </widget> | ||
| 434 | </item> | ||
| 435 | <item> | ||
| 436 | <widget class="QGroupBox" name="vibrationGroupPlayer6"> | ||
| 437 | <property name="title"> | ||
| 438 | <string>Player 8</string> | ||
| 439 | </property> | ||
| 440 | <property name="checkable"> | ||
| 441 | <bool>true</bool> | ||
| 442 | </property> | ||
| 443 | <layout class="QHBoxLayout" name="horizontalLayout_13"> | ||
| 444 | <property name="leftMargin"> | ||
| 445 | <number>3</number> | ||
| 446 | </property> | ||
| 447 | <property name="topMargin"> | ||
| 448 | <number>3</number> | ||
| 449 | </property> | ||
| 450 | <property name="rightMargin"> | ||
| 451 | <number>3</number> | ||
| 452 | </property> | ||
| 453 | <property name="bottomMargin"> | ||
| 454 | <number>3</number> | ||
| 455 | </property> | ||
| 456 | <item> | ||
| 457 | <widget class="QSpinBox" name="vibrationSpinPlayer6"> | ||
| 458 | <property name="minimumSize"> | ||
| 459 | <size> | ||
| 460 | <width>68</width> | ||
| 461 | <height>21</height> | ||
| 462 | </size> | ||
| 463 | </property> | ||
| 464 | <property name="maximumSize"> | ||
| 465 | <size> | ||
| 466 | <width>68</width> | ||
| 467 | <height>16777215</height> | ||
| 468 | </size> | ||
| 469 | </property> | ||
| 470 | <property name="suffix"> | ||
| 471 | <string>%</string> | ||
| 472 | </property> | ||
| 473 | <property name="minimum"> | ||
| 474 | <number>1</number> | ||
| 475 | </property> | ||
| 476 | <property name="maximum"> | ||
| 477 | <number>150</number> | ||
| 478 | </property> | ||
| 479 | <property name="value"> | ||
| 480 | <number>100</number> | ||
| 481 | </property> | ||
| 482 | </widget> | ||
| 483 | </item> | ||
| 484 | </layout> | ||
| 485 | </widget> | ||
| 486 | </item> | ||
| 487 | </layout> | ||
| 488 | </widget> | ||
| 489 | </item> | ||
| 490 | </layout> | ||
| 491 | </widget> | ||
| 492 | </item> | ||
| 493 | <item> | ||
| 494 | <widget class="QGroupBox" name="vibrationSettingsGroup"> | ||
| 495 | <property name="title"> | ||
| 496 | <string>Settings</string> | ||
| 497 | </property> | ||
| 498 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 499 | <item> | ||
| 500 | <widget class="QCheckBox" name="checkBoxAccurateVibration"> | ||
| 501 | <property name="text"> | ||
| 502 | <string>Enable Accurate Vibration</string> | ||
| 503 | </property> | ||
| 504 | </widget> | ||
| 505 | </item> | ||
| 506 | </layout> | ||
| 507 | </widget> | ||
| 508 | </item> | ||
| 509 | <item> | ||
| 510 | <spacer name="spacerVibration"> | ||
| 511 | <property name="orientation"> | ||
| 512 | <enum>Qt::Vertical</enum> | ||
| 513 | </property> | ||
| 514 | <property name="sizeHint" stdset="0"> | ||
| 515 | <size> | ||
| 516 | <width>167</width> | ||
| 517 | <height>55</height> | ||
| 518 | </size> | ||
| 519 | </property> | ||
| 520 | </spacer> | ||
| 521 | </item> | ||
| 522 | <item> | ||
| 523 | <widget class="QDialogButtonBox" name="buttonBoxVibration"> | ||
| 524 | <property name="standardButtons"> | ||
| 525 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 526 | </property> | ||
| 527 | </widget> | ||
| 528 | </item> | ||
| 529 | </layout> | ||
| 530 | </widget> | ||
| 531 | <resources/> | ||
| 532 | <connections> | ||
| 533 | <connection> | ||
| 534 | <sender>buttonBoxVibration</sender> | ||
| 535 | <signal>accepted()</signal> | ||
| 536 | <receiver>ConfigureVibration</receiver> | ||
| 537 | <slot>accept()</slot> | ||
| 538 | </connection> | ||
| 539 | <connection> | ||
| 540 | <sender>buttonBoxVibration</sender> | ||
| 541 | <signal>rejected()</signal> | ||
| 542 | <receiver>ConfigureVibration</receiver> | ||
| 543 | <slot>reject()</slot> | ||
| 544 | </connection> | ||
| 545 | </connections> | ||
| 546 | </ui> | ||
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp new file mode 100644 index 000000000..e87aededb --- /dev/null +++ b/src/yuzu/configuration/input_profiles.cpp | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "common/common_paths.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | #include "yuzu/configuration/config.h" | ||
| 10 | #include "yuzu/configuration/input_profiles.h" | ||
| 11 | |||
| 12 | namespace FS = Common::FS; | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | bool ProfileExistsInFilesystem(std::string_view profile_name) { | ||
| 17 | return FS::Exists(fmt::format("{}input" DIR_SEP "{}.ini", | ||
| 18 | FS::GetUserPath(FS::UserPath::ConfigDir), profile_name)); | ||
| 19 | } | ||
| 20 | |||
| 21 | bool IsINI(std::string_view filename) { | ||
| 22 | const std::size_t index = filename.rfind('.'); | ||
| 23 | |||
| 24 | if (index == std::string::npos) { | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | |||
| 28 | return filename.substr(index) == ".ini"; | ||
| 29 | } | ||
| 30 | |||
| 31 | std::string GetNameWithoutExtension(const std::string& filename) { | ||
| 32 | const std::size_t index = filename.rfind('.'); | ||
| 33 | |||
| 34 | if (index == std::string::npos) { | ||
| 35 | return filename; | ||
| 36 | } | ||
| 37 | |||
| 38 | return filename.substr(0, index); | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace | ||
| 42 | |||
| 43 | InputProfiles::InputProfiles() { | ||
| 44 | const std::string input_profile_loc = | ||
| 45 | fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir)); | ||
| 46 | |||
| 47 | FS::ForeachDirectoryEntry( | ||
| 48 | nullptr, input_profile_loc, | ||
| 49 | [this](u64* entries_out, const std::string& directory, const std::string& filename) { | ||
| 50 | if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) { | ||
| 51 | map_profiles.insert_or_assign( | ||
| 52 | GetNameWithoutExtension(filename), | ||
| 53 | std::make_unique<Config>(GetNameWithoutExtension(filename), | ||
| 54 | Config::ConfigType::InputProfile)); | ||
| 55 | } | ||
| 56 | return true; | ||
| 57 | }); | ||
| 58 | } | ||
| 59 | |||
| 60 | InputProfiles::~InputProfiles() = default; | ||
| 61 | |||
| 62 | std::vector<std::string> InputProfiles::GetInputProfileNames() { | ||
| 63 | std::vector<std::string> profile_names; | ||
| 64 | profile_names.reserve(map_profiles.size()); | ||
| 65 | |||
| 66 | for (const auto& [profile_name, config] : map_profiles) { | ||
| 67 | if (!ProfileExistsInFilesystem(profile_name)) { | ||
| 68 | DeleteProfile(profile_name); | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | |||
| 72 | profile_names.push_back(profile_name); | ||
| 73 | } | ||
| 74 | |||
| 75 | return profile_names; | ||
| 76 | } | ||
| 77 | |||
| 78 | bool InputProfiles::IsProfileNameValid(std::string_view profile_name) { | ||
| 79 | return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos; | ||
| 80 | } | ||
| 81 | |||
| 82 | bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 83 | if (ProfileExistsInMap(profile_name)) { | ||
| 84 | return false; | ||
| 85 | } | ||
| 86 | |||
| 87 | map_profiles.insert_or_assign( | ||
| 88 | profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile)); | ||
| 89 | |||
| 90 | return SaveProfile(profile_name, player_index); | ||
| 91 | } | ||
| 92 | |||
| 93 | bool InputProfiles::DeleteProfile(const std::string& profile_name) { | ||
| 94 | if (!ProfileExistsInMap(profile_name)) { | ||
| 95 | return false; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (!ProfileExistsInFilesystem(profile_name) || | ||
| 99 | FS::Delete(map_profiles[profile_name]->GetConfigFilePath())) { | ||
| 100 | map_profiles.erase(profile_name); | ||
| 101 | } | ||
| 102 | |||
| 103 | return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name); | ||
| 104 | } | ||
| 105 | |||
| 106 | bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 107 | if (!ProfileExistsInMap(profile_name)) { | ||
| 108 | return false; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (!ProfileExistsInFilesystem(profile_name)) { | ||
| 112 | map_profiles.erase(profile_name); | ||
| 113 | return false; | ||
| 114 | } | ||
| 115 | |||
| 116 | map_profiles[profile_name]->ReadControlPlayerValue(player_index); | ||
| 117 | return true; | ||
| 118 | } | ||
| 119 | |||
| 120 | bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 121 | if (!ProfileExistsInMap(profile_name)) { | ||
| 122 | return false; | ||
| 123 | } | ||
| 124 | |||
| 125 | map_profiles[profile_name]->SaveControlPlayerValue(player_index); | ||
| 126 | return true; | ||
| 127 | } | ||
| 128 | |||
| 129 | bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const { | ||
| 130 | return map_profiles.find(profile_name) != map_profiles.end(); | ||
| 131 | } | ||
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h new file mode 100644 index 000000000..cb41fd9be --- /dev/null +++ b/src/yuzu/configuration/input_profiles.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | #include <string_view> | ||
| 9 | #include <unordered_map> | ||
| 10 | |||
| 11 | class Config; | ||
| 12 | |||
| 13 | class InputProfiles { | ||
| 14 | |||
| 15 | public: | ||
| 16 | explicit InputProfiles(); | ||
| 17 | virtual ~InputProfiles(); | ||
| 18 | |||
| 19 | std::vector<std::string> GetInputProfileNames(); | ||
| 20 | |||
| 21 | static bool IsProfileNameValid(std::string_view profile_name); | ||
| 22 | |||
| 23 | bool CreateProfile(const std::string& profile_name, std::size_t player_index); | ||
| 24 | bool DeleteProfile(const std::string& profile_name); | ||
| 25 | bool LoadProfile(const std::string& profile_name, std::size_t player_index); | ||
| 26 | bool SaveProfile(const std::string& profile_name, std::size_t player_index); | ||
| 27 | |||
| 28 | private: | ||
| 29 | bool ProfileExistsInMap(const std::string& profile_name) const; | ||
| 30 | |||
| 31 | std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles; | ||
| 32 | }; | ||
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index e0ce45fd9..23643aea2 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -235,12 +235,11 @@ GameListWorker::~GameListWorker() = default; | |||
| 235 | void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { | 235 | void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { |
| 236 | using namespace FileSys; | 236 | using namespace FileSys; |
| 237 | 237 | ||
| 238 | const auto& cache = | 238 | auto& system = Core::System::GetInstance(); |
| 239 | dynamic_cast<ContentProviderUnion&>(Core::System::GetInstance().GetContentProvider()); | 239 | const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider()); |
| 240 | 240 | ||
| 241 | std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> installed_games; | 241 | auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, |
| 242 | installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, | 242 | ContentRecordType::Program); |
| 243 | ContentRecordType::Program); | ||
| 244 | 243 | ||
| 245 | if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) { | 244 | if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) { |
| 246 | installed_games = cache.ListEntriesFilterOrigin( | 245 | installed_games = cache.ListEntriesFilterOrigin( |
| @@ -254,23 +253,27 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { | |||
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | for (const auto& [slot, game] : installed_games) { | 255 | for (const auto& [slot, game] : installed_games) { |
| 257 | if (slot == ContentProviderUnionSlot::FrontendManual) | 256 | if (slot == ContentProviderUnionSlot::FrontendManual) { |
| 258 | continue; | 257 | continue; |
| 258 | } | ||
| 259 | 259 | ||
| 260 | const auto file = cache.GetEntryUnparsed(game.title_id, game.type); | 260 | const auto file = cache.GetEntryUnparsed(game.title_id, game.type); |
| 261 | std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file); | 261 | std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(system, file); |
| 262 | if (!loader) | 262 | if (!loader) { |
| 263 | continue; | 263 | continue; |
| 264 | } | ||
| 264 | 265 | ||
| 265 | std::vector<u8> icon; | 266 | std::vector<u8> icon; |
| 266 | std::string name; | 267 | std::string name; |
| 267 | u64 program_id = 0; | 268 | u64 program_id = 0; |
| 268 | loader->ReadProgramId(program_id); | 269 | loader->ReadProgramId(program_id); |
| 269 | 270 | ||
| 270 | const PatchManager patch{program_id}; | 271 | const PatchManager patch{program_id, system.GetFileSystemController(), |
| 272 | system.GetContentProvider()}; | ||
| 271 | const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control); | 273 | const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control); |
| 272 | if (control != nullptr) | 274 | if (control != nullptr) { |
| 273 | GetMetadataFromControlNCA(patch, *control, icon, name); | 275 | GetMetadataFromControlNCA(patch, *control, icon, name); |
| 276 | } | ||
| 274 | 277 | ||
| 275 | emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id, | 278 | emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id, |
| 276 | compatibility_list, patch), | 279 | compatibility_list, patch), |
| @@ -280,9 +283,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { | |||
| 280 | 283 | ||
| 281 | void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, | 284 | void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, |
| 282 | unsigned int recursion, GameListDir* parent_dir) { | 285 | unsigned int recursion, GameListDir* parent_dir) { |
| 283 | const auto callback = [this, target, recursion, | 286 | auto& system = Core::System::GetInstance(); |
| 284 | parent_dir](u64* num_entries_out, const std::string& directory, | 287 | |
| 285 | const std::string& virtual_name) -> bool { | 288 | const auto callback = [this, target, recursion, parent_dir, |
| 289 | &system](u64* num_entries_out, const std::string& directory, | ||
| 290 | const std::string& virtual_name) -> bool { | ||
| 286 | if (stop_processing) { | 291 | if (stop_processing) { |
| 287 | // Breaks the callback loop. | 292 | // Breaks the callback loop. |
| 288 | return false; | 293 | return false; |
| @@ -293,7 +298,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 293 | if (!is_dir && | 298 | if (!is_dir && |
| 294 | (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { | 299 | (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { |
| 295 | const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); | 300 | const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); |
| 296 | auto loader = Loader::GetLoader(file); | 301 | auto loader = Loader::GetLoader(system, file); |
| 297 | if (!loader) { | 302 | if (!loader) { |
| 298 | return true; | 303 | return true; |
| 299 | } | 304 | } |
| @@ -331,7 +336,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 331 | std::string name = " "; | 336 | std::string name = " "; |
| 332 | [[maybe_unused]] const auto res3 = loader->ReadTitle(name); | 337 | [[maybe_unused]] const auto res3 = loader->ReadTitle(name); |
| 333 | 338 | ||
| 334 | const FileSys::PatchManager patch{program_id}; | 339 | const FileSys::PatchManager patch{program_id, system.GetFileSystemController(), |
| 340 | system.GetContentProvider()}; | ||
| 335 | 341 | ||
| 336 | emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id, | 342 | emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id, |
| 337 | compatibility_list, patch), | 343 | compatibility_list, patch), |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 18e68e590..805619ccf 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "applets/web_browser.h" | 18 | #include "applets/web_browser.h" |
| 19 | #include "configuration/configure_input.h" | 19 | #include "configuration/configure_input.h" |
| 20 | #include "configuration/configure_per_game.h" | 20 | #include "configuration/configure_per_game.h" |
| 21 | #include "configuration/configure_vibration.h" | ||
| 21 | #include "core/file_sys/vfs.h" | 22 | #include "core/file_sys/vfs.h" |
| 22 | #include "core/file_sys/vfs_real.h" | 23 | #include "core/file_sys/vfs_real.h" |
| 23 | #include "core/frontend/applets/controller.h" | 24 | #include "core/frontend/applets/controller.h" |
| @@ -50,12 +51,14 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 50 | #include <QDesktopServices> | 51 | #include <QDesktopServices> |
| 51 | #include <QDesktopWidget> | 52 | #include <QDesktopWidget> |
| 52 | #include <QDialogButtonBox> | 53 | #include <QDialogButtonBox> |
| 54 | #include <QDir> | ||
| 53 | #include <QFile> | 55 | #include <QFile> |
| 54 | #include <QFileDialog> | 56 | #include <QFileDialog> |
| 55 | #include <QInputDialog> | 57 | #include <QInputDialog> |
| 56 | #include <QMessageBox> | 58 | #include <QMessageBox> |
| 57 | #include <QProgressBar> | 59 | #include <QProgressBar> |
| 58 | #include <QProgressDialog> | 60 | #include <QProgressDialog> |
| 61 | #include <QPushButton> | ||
| 59 | #include <QShortcut> | 62 | #include <QShortcut> |
| 60 | #include <QStatusBar> | 63 | #include <QStatusBar> |
| 61 | #include <QSysInfo> | 64 | #include <QSysInfo> |
| @@ -277,6 +280,8 @@ GMainWindow::GMainWindow() | |||
| 277 | if (args.length() >= 2) { | 280 | if (args.length() >= 2) { |
| 278 | BootGame(args[1]); | 281 | BootGame(args[1]); |
| 279 | } | 282 | } |
| 283 | |||
| 284 | MigrateConfigFiles(); | ||
| 280 | } | 285 | } |
| 281 | 286 | ||
| 282 | GMainWindow::~GMainWindow() { | 287 | GMainWindow::~GMainWindow() { |
| @@ -288,6 +293,7 @@ GMainWindow::~GMainWindow() { | |||
| 288 | void GMainWindow::ControllerSelectorReconfigureControllers( | 293 | void GMainWindow::ControllerSelectorReconfigureControllers( |
| 289 | const Core::Frontend::ControllerParameters& parameters) { | 294 | const Core::Frontend::ControllerParameters& parameters) { |
| 290 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); | 295 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); |
| 296 | |||
| 291 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | | 297 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | |
| 292 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); | 298 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); |
| 293 | dialog.setWindowModality(Qt::WindowModal); | 299 | dialog.setWindowModality(Qt::WindowModal); |
| @@ -547,13 +553,14 @@ void GMainWindow::InitializeWidgets() { | |||
| 547 | dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); | 553 | dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); |
| 548 | dock_status_button->setFocusPolicy(Qt::NoFocus); | 554 | dock_status_button->setFocusPolicy(Qt::NoFocus); |
| 549 | connect(dock_status_button, &QPushButton::clicked, [&] { | 555 | connect(dock_status_button, &QPushButton::clicked, [&] { |
| 550 | Settings::values.use_docked_mode = !Settings::values.use_docked_mode; | 556 | Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue()); |
| 551 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 557 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 552 | OnDockedModeChanged(!Settings::values.use_docked_mode, Settings::values.use_docked_mode); | 558 | OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), |
| 559 | Settings::values.use_docked_mode.GetValue()); | ||
| 553 | }); | 560 | }); |
| 554 | dock_status_button->setText(tr("DOCK")); | 561 | dock_status_button->setText(tr("DOCK")); |
| 555 | dock_status_button->setCheckable(true); | 562 | dock_status_button->setCheckable(true); |
| 556 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 563 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 557 | statusBar()->insertPermanentWidget(0, dock_status_button); | 564 | statusBar()->insertPermanentWidget(0, dock_status_button); |
| 558 | 565 | ||
| 559 | // Setup ASync button | 566 | // Setup ASync button |
| @@ -792,10 +799,11 @@ void GMainWindow::InitializeHotkeys() { | |||
| 792 | }); | 799 | }); |
| 793 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), | 800 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), |
| 794 | &QShortcut::activated, this, [&] { | 801 | &QShortcut::activated, this, [&] { |
| 795 | Settings::values.use_docked_mode = !Settings::values.use_docked_mode; | 802 | Settings::values.use_docked_mode.SetValue( |
| 796 | OnDockedModeChanged(!Settings::values.use_docked_mode, | 803 | !Settings::values.use_docked_mode.GetValue()); |
| 797 | Settings::values.use_docked_mode); | 804 | OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), |
| 798 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 805 | Settings::values.use_docked_mode.GetValue()); |
| 806 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); | ||
| 799 | }); | 807 | }); |
| 800 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), | 808 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), |
| 801 | &QShortcut::activated, this, | 809 | &QShortcut::activated, this, |
| @@ -970,7 +978,7 @@ void GMainWindow::AllowOSSleep() { | |||
| 970 | #endif | 978 | #endif |
| 971 | } | 979 | } |
| 972 | 980 | ||
| 973 | bool GMainWindow::LoadROM(const QString& filename) { | 981 | bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) { |
| 974 | // Shutdown previous session if the emu thread is still active... | 982 | // Shutdown previous session if the emu thread is still active... |
| 975 | if (emu_thread != nullptr) | 983 | if (emu_thread != nullptr) |
| 976 | ShutdownGame(); | 984 | ShutdownGame(); |
| @@ -995,7 +1003,8 @@ bool GMainWindow::LoadROM(const QString& filename) { | |||
| 995 | 1003 | ||
| 996 | system.RegisterHostThread(); | 1004 | system.RegisterHostThread(); |
| 997 | 1005 | ||
| 998 | const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; | 1006 | const Core::System::ResultStatus result{ |
| 1007 | system.Load(*render_window, filename.toStdString(), program_index)}; | ||
| 999 | 1008 | ||
| 1000 | const auto drd_callout = | 1009 | const auto drd_callout = |
| 1001 | (UISettings::values.callout_flags & static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; | 1010 | (UISettings::values.callout_flags & static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; |
| @@ -1077,26 +1086,32 @@ void GMainWindow::SelectAndSetCurrentUser() { | |||
| 1077 | Settings::values.current_user = dialog.GetIndex(); | 1086 | Settings::values.current_user = dialog.GetIndex(); |
| 1078 | } | 1087 | } |
| 1079 | 1088 | ||
| 1080 | void GMainWindow::BootGame(const QString& filename) { | 1089 | void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { |
| 1081 | LOG_INFO(Frontend, "yuzu starting..."); | 1090 | LOG_INFO(Frontend, "yuzu starting..."); |
| 1082 | StoreRecentFile(filename); // Put the filename on top of the list | 1091 | StoreRecentFile(filename); // Put the filename on top of the list |
| 1083 | 1092 | ||
| 1084 | u64 title_id{0}; | 1093 | u64 title_id{0}; |
| 1085 | 1094 | ||
| 1095 | last_filename_booted = filename; | ||
| 1096 | |||
| 1097 | auto& system = Core::System::GetInstance(); | ||
| 1086 | const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); | 1098 | const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); |
| 1087 | const auto loader = Loader::GetLoader(v_file); | 1099 | const auto loader = Loader::GetLoader(system, v_file, program_index); |
| 1100 | |||
| 1088 | if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { | 1101 | if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { |
| 1089 | // Load per game settings | 1102 | // Load per game settings |
| 1090 | Config per_game_config(fmt::format("{:016X}.ini", title_id), false); | 1103 | Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig); |
| 1091 | } | 1104 | } |
| 1092 | 1105 | ||
| 1106 | ConfigureVibration::SetAllVibrationDevices(); | ||
| 1107 | |||
| 1093 | Settings::LogSettings(); | 1108 | Settings::LogSettings(); |
| 1094 | 1109 | ||
| 1095 | if (UISettings::values.select_user_on_boot) { | 1110 | if (UISettings::values.select_user_on_boot) { |
| 1096 | SelectAndSetCurrentUser(); | 1111 | SelectAndSetCurrentUser(); |
| 1097 | } | 1112 | } |
| 1098 | 1113 | ||
| 1099 | if (!LoadROM(filename)) | 1114 | if (!LoadROM(filename, program_index)) |
| 1100 | return; | 1115 | return; |
| 1101 | 1116 | ||
| 1102 | // Create and start the emulation thread | 1117 | // Create and start the emulation thread |
| @@ -1104,6 +1119,10 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1104 | emit EmulationStarting(emu_thread.get()); | 1119 | emit EmulationStarting(emu_thread.get()); |
| 1105 | emu_thread->start(); | 1120 | emu_thread->start(); |
| 1106 | 1121 | ||
| 1122 | // Register an ExecuteProgram callback such that Core can execute a sub-program | ||
| 1123 | system.RegisterExecuteProgramCallback( | ||
| 1124 | [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); | ||
| 1125 | |||
| 1107 | connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); | 1126 | connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); |
| 1108 | // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views | 1127 | // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views |
| 1109 | // before the CPU continues | 1128 | // before the CPU continues |
| @@ -1134,9 +1153,13 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1134 | 1153 | ||
| 1135 | std::string title_name; | 1154 | std::string title_name; |
| 1136 | std::string title_version; | 1155 | std::string title_version; |
| 1137 | const auto res = Core::System::GetInstance().GetGameName(title_name); | 1156 | const auto res = system.GetGameName(title_name); |
| 1138 | 1157 | ||
| 1139 | const auto metadata = FileSys::PatchManager(title_id).GetControlMetadata(); | 1158 | const auto metadata = [&system, title_id] { |
| 1159 | const FileSys::PatchManager pm(title_id, system.GetFileSystemController(), | ||
| 1160 | system.GetContentProvider()); | ||
| 1161 | return pm.GetControlMetadata(); | ||
| 1162 | }(); | ||
| 1140 | if (metadata.first != nullptr) { | 1163 | if (metadata.first != nullptr) { |
| 1141 | title_version = metadata.first->GetVersionString(); | 1164 | title_version = metadata.first->GetVersionString(); |
| 1142 | title_name = metadata.first->GetApplicationName(); | 1165 | title_name = metadata.first->GetApplicationName(); |
| @@ -1147,7 +1170,7 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1147 | LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); | 1170 | LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); |
| 1148 | UpdateWindowTitle(title_name, title_version); | 1171 | UpdateWindowTitle(title_name, title_version); |
| 1149 | 1172 | ||
| 1150 | loading_screen->Prepare(Core::System::GetInstance().GetAppLoader()); | 1173 | loading_screen->Prepare(system.GetAppLoader()); |
| 1151 | loading_screen->show(); | 1174 | loading_screen->show(); |
| 1152 | 1175 | ||
| 1153 | emulation_running = true; | 1176 | emulation_running = true; |
| @@ -1266,16 +1289,18 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||
| 1266 | const std::string& game_path) { | 1289 | const std::string& game_path) { |
| 1267 | std::string path; | 1290 | std::string path; |
| 1268 | QString open_target; | 1291 | QString open_target; |
| 1292 | auto& system = Core::System::GetInstance(); | ||
| 1269 | 1293 | ||
| 1270 | const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] { | 1294 | const auto [user_save_size, device_save_size] = [this, &game_path, &program_id, &system] { |
| 1271 | FileSys::PatchManager pm{program_id}; | 1295 | const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), |
| 1296 | system.GetContentProvider()}; | ||
| 1272 | const auto control = pm.GetControlMetadata().first; | 1297 | const auto control = pm.GetControlMetadata().first; |
| 1273 | if (control != nullptr) { | 1298 | if (control != nullptr) { |
| 1274 | return std::make_pair(control->GetDefaultNormalSaveSize(), | 1299 | return std::make_pair(control->GetDefaultNormalSaveSize(), |
| 1275 | control->GetDeviceSaveDataSize()); | 1300 | control->GetDeviceSaveDataSize()); |
| 1276 | } else { | 1301 | } else { |
| 1277 | const auto file = Core::GetGameFileFromPath(vfs, game_path); | 1302 | const auto file = Core::GetGameFileFromPath(vfs, game_path); |
| 1278 | const auto loader = Loader::GetLoader(file); | 1303 | const auto loader = Loader::GetLoader(system, file); |
| 1279 | 1304 | ||
| 1280 | FileSys::NACP nacp{}; | 1305 | FileSys::NACP nacp{}; |
| 1281 | loader->ReadControlData(nacp); | 1306 | loader->ReadControlData(nacp); |
| @@ -1577,7 +1602,8 @@ void GMainWindow::RemoveCustomConfiguration(u64 program_id) { | |||
| 1577 | const QString config_dir = | 1602 | const QString config_dir = |
| 1578 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); | 1603 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); |
| 1579 | const QString custom_config_file_path = | 1604 | const QString custom_config_file_path = |
| 1580 | config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id)); | 1605 | config_dir + QStringLiteral("custom") + QDir::separator() + |
| 1606 | QString::fromStdString(fmt::format("{:016X}.ini", program_id)); | ||
| 1581 | 1607 | ||
| 1582 | if (!QFile::exists(custom_config_file_path)) { | 1608 | if (!QFile::exists(custom_config_file_path)) { |
| 1583 | QMessageBox::warning(this, tr("Error Removing Custom Configuration"), | 1609 | QMessageBox::warning(this, tr("Error Removing Custom Configuration"), |
| @@ -1601,7 +1627,8 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 1601 | "cancelled the operation.")); | 1627 | "cancelled the operation.")); |
| 1602 | }; | 1628 | }; |
| 1603 | 1629 | ||
| 1604 | const auto loader = Loader::GetLoader(vfs->OpenFile(game_path, FileSys::Mode::Read)); | 1630 | auto& system = Core::System::GetInstance(); |
| 1631 | const auto loader = Loader::GetLoader(system, vfs->OpenFile(game_path, FileSys::Mode::Read)); | ||
| 1605 | if (loader == nullptr) { | 1632 | if (loader == nullptr) { |
| 1606 | failed(); | 1633 | failed(); |
| 1607 | return; | 1634 | return; |
| @@ -1613,7 +1640,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 1613 | return; | 1640 | return; |
| 1614 | } | 1641 | } |
| 1615 | 1642 | ||
| 1616 | const auto& installed = Core::System::GetInstance().GetContentProvider(); | 1643 | const auto& installed = system.GetContentProvider(); |
| 1617 | const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); | 1644 | const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); |
| 1618 | 1645 | ||
| 1619 | if (!romfs_title_id) { | 1646 | if (!romfs_title_id) { |
| @@ -1628,7 +1655,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 1628 | 1655 | ||
| 1629 | if (*romfs_title_id == program_id) { | 1656 | if (*romfs_title_id == program_id) { |
| 1630 | const u64 ivfc_offset = loader->ReadRomFSIVFCOffset(); | 1657 | const u64 ivfc_offset = loader->ReadRomFSIVFCOffset(); |
| 1631 | FileSys::PatchManager pm{program_id}; | 1658 | const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), installed}; |
| 1632 | romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program); | 1659 | romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program); |
| 1633 | } else { | 1660 | } else { |
| 1634 | romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); | 1661 | romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); |
| @@ -1745,7 +1772,8 @@ void GMainWindow::OnGameListShowList(bool show) { | |||
| 1745 | void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { | 1772 | void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { |
| 1746 | u64 title_id{}; | 1773 | u64 title_id{}; |
| 1747 | const auto v_file = Core::GetGameFileFromPath(vfs, file); | 1774 | const auto v_file = Core::GetGameFileFromPath(vfs, file); |
| 1748 | const auto loader = Loader::GetLoader(v_file); | 1775 | const auto loader = Loader::GetLoader(Core::System::GetInstance(), v_file); |
| 1776 | |||
| 1749 | if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | 1777 | if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { |
| 1750 | QMessageBox::information(this, tr("Properties"), | 1778 | QMessageBox::information(this, tr("Properties"), |
| 1751 | tr("The game properties could not be loaded.")); | 1779 | tr("The game properties could not be loaded.")); |
| @@ -2117,6 +2145,11 @@ void GMainWindow::OnLoadComplete() { | |||
| 2117 | loading_screen->OnLoadComplete(); | 2145 | loading_screen->OnLoadComplete(); |
| 2118 | } | 2146 | } |
| 2119 | 2147 | ||
| 2148 | void GMainWindow::OnExecuteProgram(std::size_t program_index) { | ||
| 2149 | ShutdownGame(); | ||
| 2150 | BootGame(last_filename_booted, program_index); | ||
| 2151 | } | ||
| 2152 | |||
| 2120 | void GMainWindow::ErrorDisplayDisplayError(QString body) { | 2153 | void GMainWindow::ErrorDisplayDisplayError(QString body) { |
| 2121 | QMessageBox::critical(this, tr("Error Display"), body); | 2154 | QMessageBox::critical(this, tr("Error Display"), body); |
| 2122 | emit ErrorDisplayFinished(); | 2155 | emit ErrorDisplayFinished(); |
| @@ -2393,6 +2426,29 @@ void GMainWindow::OnCaptureScreenshot() { | |||
| 2393 | OnStartGame(); | 2426 | OnStartGame(); |
| 2394 | } | 2427 | } |
| 2395 | 2428 | ||
| 2429 | // TODO: Written 2020-10-01: Remove per-game config migration code when it is irrelevant | ||
| 2430 | void GMainWindow::MigrateConfigFiles() { | ||
| 2431 | const std::string& config_dir_str = Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir); | ||
| 2432 | const QDir config_dir = QDir(QString::fromStdString(config_dir_str)); | ||
| 2433 | const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini"))); | ||
| 2434 | |||
| 2435 | Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str)); | ||
| 2436 | for (QStringList::const_iterator it = config_dir_list.constBegin(); | ||
| 2437 | it != config_dir_list.constEnd(); ++it) { | ||
| 2438 | const auto filename = it->toStdString(); | ||
| 2439 | if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) { | ||
| 2440 | continue; | ||
| 2441 | } | ||
| 2442 | const auto origin = fmt::format("{}{}", config_dir_str, filename); | ||
| 2443 | const auto destination = fmt::format("{}custom" DIR_SEP "{}", config_dir_str, filename); | ||
| 2444 | LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); | ||
| 2445 | if (!Common::FS::Rename(origin, destination)) { | ||
| 2446 | // Delete the old config file if one already exists in the new location. | ||
| 2447 | Common::FS::Delete(origin); | ||
| 2448 | } | ||
| 2449 | } | ||
| 2450 | } | ||
| 2451 | |||
| 2396 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, | 2452 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, |
| 2397 | const std::string& title_version) { | 2453 | const std::string& title_version) { |
| 2398 | const auto full_name = std::string(Common::g_build_fullname); | 2454 | const auto full_name = std::string(Common::g_build_fullname); |
| @@ -2450,7 +2506,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2450 | } | 2506 | } |
| 2451 | 2507 | ||
| 2452 | void GMainWindow::UpdateStatusButtons() { | 2508 | void GMainWindow::UpdateStatusButtons() { |
| 2453 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 2509 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 2454 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); | 2510 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); |
| 2455 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | 2511 | Settings::values.use_asynchronous_gpu_emulation.SetValue( |
| 2456 | Settings::values.use_asynchronous_gpu_emulation.GetValue() || | 2512 | Settings::values.use_asynchronous_gpu_emulation.GetValue() || |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index afcfa68a9..6242341d1 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -131,6 +131,7 @@ signals: | |||
| 131 | 131 | ||
| 132 | public slots: | 132 | public slots: |
| 133 | void OnLoadComplete(); | 133 | void OnLoadComplete(); |
| 134 | void OnExecuteProgram(std::size_t program_index); | ||
| 134 | void ControllerSelectorReconfigureControllers( | 135 | void ControllerSelectorReconfigureControllers( |
| 135 | const Core::Frontend::ControllerParameters& parameters); | 136 | const Core::Frontend::ControllerParameters& parameters); |
| 136 | void ErrorDisplayDisplayError(QString body); | 137 | void ErrorDisplayDisplayError(QString body); |
| @@ -154,8 +155,8 @@ private: | |||
| 154 | void PreventOSSleep(); | 155 | void PreventOSSleep(); |
| 155 | void AllowOSSleep(); | 156 | void AllowOSSleep(); |
| 156 | 157 | ||
| 157 | bool LoadROM(const QString& filename); | 158 | bool LoadROM(const QString& filename, std::size_t program_index); |
| 158 | void BootGame(const QString& filename); | 159 | void BootGame(const QString& filename, std::size_t program_index = 0); |
| 159 | void ShutdownGame(); | 160 | void ShutdownGame(); |
| 160 | 161 | ||
| 161 | void ShowTelemetryCallout(); | 162 | void ShowTelemetryCallout(); |
| @@ -251,6 +252,7 @@ private: | |||
| 251 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); | 252 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); |
| 252 | InstallResult InstallNSPXCI(const QString& filename); | 253 | InstallResult InstallNSPXCI(const QString& filename); |
| 253 | InstallResult InstallNCA(const QString& filename); | 254 | InstallResult InstallNCA(const QString& filename); |
| 255 | void MigrateConfigFiles(); | ||
| 254 | void UpdateWindowTitle(const std::string& title_name = {}, | 256 | void UpdateWindowTitle(const std::string& title_name = {}, |
| 255 | const std::string& title_version = {}); | 257 | const std::string& title_version = {}); |
| 256 | void UpdateStatusBar(); | 258 | void UpdateStatusBar(); |
| @@ -316,6 +318,9 @@ private: | |||
| 316 | // Install progress dialog | 318 | // Install progress dialog |
| 317 | QProgressDialog* install_progress; | 319 | QProgressDialog* install_progress; |
| 318 | 320 | ||
| 321 | // Last game booted, used for multi-process apps | ||
| 322 | QString last_filename_booted; | ||
| 323 | |||
| 319 | protected: | 324 | protected: |
| 320 | void dropEvent(QDropEvent* event) override; | 325 | void dropEvent(QDropEvent* event) override; |
| 321 | void dragEnterEvent(QDragEnterEvent* event) override; | 326 | void dragEnterEvent(QDragEnterEvent* event) override; |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 334038ef9..e1adbbf2b 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -228,24 +228,24 @@ static const std::array<int, 8> keyboard_mods{ | |||
| 228 | 228 | ||
| 229 | void Config::ReadValues() { | 229 | void Config::ReadValues() { |
| 230 | // Controls | 230 | // Controls |
| 231 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 231 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 232 | const auto group = fmt::format("ControlsP{}", p); | 232 | const auto group = fmt::format("ControlsP{}", p); |
| 233 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 233 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 234 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 234 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 235 | Settings::values.players[p].buttons[i] = | 235 | Settings::values.players.GetValue()[p].buttons[i] = |
| 236 | sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); | 236 | sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); |
| 237 | if (Settings::values.players[p].buttons[i].empty()) | 237 | if (Settings::values.players.GetValue()[p].buttons[i].empty()) |
| 238 | Settings::values.players[p].buttons[i] = default_param; | 238 | Settings::values.players.GetValue()[p].buttons[i] = default_param; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 241 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 242 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 242 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 243 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 243 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 244 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 244 | default_analogs[i][3], default_analogs[i][4], 0.5f); |
| 245 | Settings::values.players[p].analogs[i] = | 245 | Settings::values.players.GetValue()[p].analogs[i] = |
| 246 | sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); | 246 | sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); |
| 247 | if (Settings::values.players[p].analogs[i].empty()) | 247 | if (Settings::values.players.GetValue()[p].analogs[i].empty()) |
| 248 | Settings::values.players[p].analogs[i] = default_param; | 248 | Settings::values.players.GetValue()[p].analogs[i] = default_param; |
| 249 | } | 249 | } |
| 250 | } | 250 | } |
| 251 | 251 | ||
| @@ -288,10 +288,12 @@ void Config::ReadValues() { | |||
| 288 | Settings::values.debug_pad_analogs[i] = default_param; | 288 | Settings::values.debug_pad_analogs[i] = default_param; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | Settings::values.vibration_enabled = | 291 | Settings::values.vibration_enabled.SetValue( |
| 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true); | 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true)); |
| 293 | Settings::values.motion_enabled = | 293 | Settings::values.enable_accurate_vibrations.SetValue( |
| 294 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true); | 294 | sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false)); |
| 295 | Settings::values.motion_enabled.SetValue( | ||
| 296 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); | ||
| 295 | Settings::values.touchscreen.enabled = | 297 | Settings::values.touchscreen.enabled = |
| 296 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 298 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 297 | Settings::values.touchscreen.device = | 299 | Settings::values.touchscreen.device = |
| @@ -343,7 +345,8 @@ void Config::ReadValues() { | |||
| 343 | Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); | 345 | Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); |
| 344 | 346 | ||
| 345 | // System | 347 | // System |
| 346 | Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); | 348 | Settings::values.use_docked_mode.SetValue( |
| 349 | sdl2_config->GetBoolean("System", "use_docked_mode", false)); | ||
| 347 | const auto size = sdl2_config->GetInteger("System", "users_size", 0); | 350 | const auto size = sdl2_config->GetInteger("System", "users_size", 0); |
| 348 | 351 | ||
| 349 | Settings::values.current_user = std::clamp<int>( | 352 | Settings::values.current_user = std::clamp<int>( |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 796e27df4..bcbbcd4ca 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -65,6 +65,14 @@ button_screenshot= | |||
| 65 | lstick= | 65 | lstick= |
| 66 | rstick= | 66 | rstick= |
| 67 | 67 | ||
| 68 | # Whether to enable or disable vibration | ||
| 69 | # 0: Disabled, 1 (default): Enabled | ||
| 70 | vibration_enabled= | ||
| 71 | |||
| 72 | # Whether to enable or disable accurate vibrations | ||
| 73 | # 0 (default): Disabled, 1: Enabled | ||
| 74 | enable_accurate_vibrations= | ||
| 75 | |||
| 68 | # for motion input, the following devices are available: | 76 | # for motion input, the following devices are available: |
| 69 | # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: | 77 | # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: |
| 70 | # - "update_period": update period in milliseconds (default to 100) | 78 | # - "update_period": update period in milliseconds (default to 100) |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 3a76c785f..14a23c71b 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -240,11 +240,11 @@ int main(int argc, char** argv) { | |||
| 240 | system.CurrentProcess()->GetTitleID(), false, | 240 | system.CurrentProcess()->GetTitleID(), false, |
| 241 | [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); | 241 | [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); |
| 242 | 242 | ||
| 243 | system.Run(); | 243 | void(system.Run()); |
| 244 | while (emu_window->IsOpen()) { | 244 | while (emu_window->IsOpen()) { |
| 245 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | 245 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
| 246 | } | 246 | } |
| 247 | system.Pause(); | 247 | void(system.Pause()); |
| 248 | system.Shutdown(); | 248 | system.Shutdown(); |
| 249 | 249 | ||
| 250 | detached_tasks.WaitForAllTasks(); | 250 | detached_tasks.WaitForAllTasks(); |
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index bc273fb51..b6cdc7c1c 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp | |||
| @@ -47,13 +47,13 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) { | |||
| 47 | 47 | ||
| 48 | void Config::ReadValues() { | 48 | void Config::ReadValues() { |
| 49 | // Controls | 49 | // Controls |
| 50 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 50 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 51 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 51 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 52 | Settings::values.players[p].buttons[i] = ""; | 52 | Settings::values.players.GetValue()[p].buttons[i] = ""; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 55 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 56 | Settings::values.players[p].analogs[i] = ""; | 56 | Settings::values.players.GetValue()[p].analogs[i] = ""; |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -75,8 +75,9 @@ void Config::ReadValues() { | |||
| 75 | Settings::values.debug_pad_analogs[i] = ""; | 75 | Settings::values.debug_pad_analogs[i] = ""; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | Settings::values.vibration_enabled = true; | 78 | Settings::values.vibration_enabled.SetValue(true); |
| 79 | Settings::values.motion_enabled = true; | 79 | Settings::values.enable_accurate_vibrations.SetValue(false); |
| 80 | Settings::values.motion_enabled.SetValue(true); | ||
| 80 | Settings::values.touchscreen.enabled = ""; | 81 | Settings::values.touchscreen.enabled = ""; |
| 81 | Settings::values.touchscreen.device = ""; | 82 | Settings::values.touchscreen.device = ""; |
| 82 | Settings::values.touchscreen.finger = 0; | 83 | Settings::values.touchscreen.finger = 0; |
| @@ -84,8 +85,8 @@ void Config::ReadValues() { | |||
| 84 | Settings::values.touchscreen.diameter_x = 15; | 85 | Settings::values.touchscreen.diameter_x = 15; |
| 85 | Settings::values.touchscreen.diameter_y = 15; | 86 | Settings::values.touchscreen.diameter_y = 15; |
| 86 | 87 | ||
| 87 | Settings::values.use_docked_mode = | 88 | Settings::values.use_docked_mode.SetValue( |
| 88 | sdl2_config->GetBoolean("Controls", "use_docked_mode", false); | 89 | sdl2_config->GetBoolean("Controls", "use_docked_mode", false)); |
| 89 | 90 | ||
| 90 | // Data Storage | 91 | // Data Storage |
| 91 | Settings::values.use_virtual_sd = | 92 | Settings::values.use_virtual_sd = |
diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp index 5798ce43a..88e4bd1f7 100644 --- a/src/yuzu_tester/yuzu.cpp +++ b/src/yuzu_tester/yuzu.cpp | |||
| @@ -256,11 +256,11 @@ int main(int argc, char** argv) { | |||
| 256 | 256 | ||
| 257 | system.GPU().Start(); | 257 | system.GPU().Start(); |
| 258 | 258 | ||
| 259 | system.Run(); | 259 | void(system.Run()); |
| 260 | while (!finished) { | 260 | while (!finished) { |
| 261 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | 261 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
| 262 | } | 262 | } |
| 263 | system.Pause(); | 263 | void(system.Pause()); |
| 264 | 264 | ||
| 265 | detached_tasks.WaitForAllTasks(); | 265 | detached_tasks.WaitForAllTasks(); |
| 266 | return return_value; | 266 | return return_value; |