diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/file_sys/patch_manager.cpp | 43 | ||||
-rw-r--r-- | src/core/file_sys/patch_manager.h | 17 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_server.cpp | 334 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_server.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_system_server.cpp | 98 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid_system_server.h | 6 | ||||
-rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/vi/display/vi_display.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/service/vi/display/vi_display.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/vi/layer/vi_layer.h | 9 | ||||
-rw-r--r-- | src/core/hle/service/vi/vi.cpp | 14 |
13 files changed, 377 insertions, 180 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 4a3dbc6a3..612122224 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -466,12 +466,12 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs return romfs; } -PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile update_raw) const { +std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const { if (title_id == 0) { return {}; } - std::map<std::string, std::string, std::less<>> out; + std::vector<Patch> out; const auto& disabled = Settings::values.disabled_addons[title_id]; // Game Updates @@ -482,20 +482,28 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u const auto update_disabled = std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); - const auto update_label = update_disabled ? "[D] Update" : "Update"; + Patch update_patch = {.enabled = !update_disabled, + .name = "Update", + .version = "", + .type = PatchType::Update, + .program_id = title_id, + .title_id = title_id}; if (nacp != nullptr) { - out.insert_or_assign(update_label, nacp->GetVersionString()); + update_patch.version = nacp->GetVersionString(); + out.push_back(update_patch); } else { if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { const auto meta_ver = content_provider.GetEntryVersion(update_tid); if (meta_ver.value_or(0) == 0) { - out.insert_or_assign(update_label, ""); + out.push_back(update_patch); } else { - out.insert_or_assign(update_label, FormatTitleVersion(*meta_ver)); + update_patch.version = FormatTitleVersion(*meta_ver); + out.push_back(update_patch); } } else if (update_raw != nullptr) { - out.insert_or_assign(update_label, "PACKED"); + update_patch.version = "PACKED"; + out.push_back(update_patch); } } @@ -539,7 +547,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u const auto mod_disabled = std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end(); - out.insert_or_assign(mod_disabled ? "[D] " + mod->GetName() : mod->GetName(), types); + out.push_back({.enabled = !mod_disabled, + .name = mod->GetName(), + .version = types, + .type = PatchType::Mod, + .program_id = title_id, + .title_id = title_id}); } } @@ -557,7 +570,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u if (!types.empty()) { const auto mod_disabled = std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); - out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", types); + out.push_back({.enabled = !mod_disabled, + .name = "SDMC", + .version = types, + .type = PatchType::Mod, + .program_id = title_id, + .title_id = title_id}); } } @@ -584,7 +602,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u const auto dlc_disabled = std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end(); - out.insert_or_assign(dlc_disabled ? "[D] DLC" : "DLC", std::move(list)); + out.push_back({.enabled = !dlc_disabled, + .name = "DLC", + .version = std::move(list), + .type = PatchType::DLC, + .program_id = title_id, + .title_id = dlc_match.back().title_id}); } return out; diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 03e9c7301..2601b8217 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -26,12 +26,22 @@ class ContentProvider; class NCA; class NACP; +enum class PatchType { Update, DLC, Mod }; + +struct Patch { + bool enabled; + std::string name; + std::string version; + PatchType type; + u64 program_id; + u64 title_id; +}; + // A centralized class to manage patches to games. class PatchManager { public: using BuildID = std::array<u8, 0x20>; using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; - using PatchVersionNames = std::map<std::string, std::string, std::less<>>; explicit PatchManager(u64 title_id_, const Service::FileSystem::FileSystemController& fs_controller_, @@ -66,9 +76,8 @@ public: VirtualFile packed_update_raw = nullptr, bool apply_layeredfs = true) const; - // Returns a vector of pairs between patch names and patch versions. - // i.e. Update 3.2.2 will return {"Update", "3.2.2"} - [[nodiscard]] PatchVersionNames GetPatchVersionNames(VirtualFile update_raw = nullptr) const; + // Returns a vector of patches + [[nodiscard]] std::vector<Patch> GetPatches(VirtualFile update_raw = nullptr) const; // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 03ebdc137..595a3372e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -26,6 +26,7 @@ void LoopProcess(Core::System& system) { resource_manager->Initialize(); resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), true); + resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true); server_manager->RegisterNamedService( "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 1951da33b..30afed812 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -22,12 +22,16 @@ #include "hid_core/resources/mouse/mouse.h" #include "hid_core/resources/npad/npad.h" #include "hid_core/resources/npad/npad_types.h" +#include "hid_core/resources/npad/npad_vibration.h" #include "hid_core/resources/palma/palma.h" #include "hid_core/resources/six_axis/console_six_axis.h" #include "hid_core/resources/six_axis/seven_six_axis.h" #include "hid_core/resources/six_axis/six_axis.h" #include "hid_core/resources/touch_screen/gesture.h" #include "hid_core/resources/touch_screen/touch_screen.h" +#include "hid_core/resources/vibration/gc_vibration_device.h" +#include "hid_core/resources/vibration/n64_vibration_device.h" +#include "hid_core/resources/vibration/vibration_device.h" namespace Service::HID { @@ -38,7 +42,7 @@ public: : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { // clang-format off static const FunctionInfo functions[] = { - {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, + {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, }; // clang-format on @@ -46,22 +50,49 @@ public: } private: - void InitializeVibrationDevice(HLERequestContext& ctx) { + void ActivateVibrationDevice(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; - if (resource_manager != nullptr && resource_manager->GetNpad()) { - resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle); - } - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", vibration_device_handle.npad_type, vibration_device_handle.npad_id, vibration_device_handle.device_index); + const auto result = ActivateVibrationDeviceImpl(vibration_device_handle); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } + Result ActivateVibrationDeviceImpl(const Core::HID::VibrationDeviceHandle& handle) { + std::scoped_lock lock{mutex}; + + const Result is_valid = IsVibrationHandleValid(handle); + if (is_valid.IsError()) { + return is_valid; + } + + for (std::size_t i = 0; i < list_size; i++) { + if (handle.device_index == vibration_device_list[i].device_index && + handle.npad_id == vibration_device_list[i].npad_id && + handle.npad_type == vibration_device_list[i].npad_type) { + return ResultSuccess; + } + } + if (list_size == vibration_device_list.size()) { + return ResultVibrationDeviceIndexOutOfRange; + } + const Result result = resource_manager->GetVibrationDevice(handle)->Activate(); + if (result.IsError()) { + return result; + } + vibration_device_list[list_size++] = handle; + return ResultSuccess; + } + + mutable std::mutex mutex; + std::size_t list_size{}; + std::array<Core::HID::VibrationDeviceHandle, 0x100> vibration_device_list{}; std::shared_ptr<ResourceManager> resource_manager; }; @@ -153,7 +184,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, - {212, nullptr, "SendVibrationValueInBool"}, + {212, &IHidServer::SendVibrationValueInBool, "SendVibrationValueInBool"}, {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, @@ -1492,59 +1523,13 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) { void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; - const auto controller = GetResourceManager()->GetNpad(); - - Core::HID::VibrationDeviceInfo vibration_device_info; - bool check_device_index = false; - - switch (vibration_device_handle.npad_type) { - case Core::HID::NpadStyleIndex::Fullkey: - case Core::HID::NpadStyleIndex::Handheld: - case Core::HID::NpadStyleIndex::JoyconDual: - case Core::HID::NpadStyleIndex::JoyconLeft: - case Core::HID::NpadStyleIndex::JoyconRight: - vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; - check_device_index = true; - break; - case Core::HID::NpadStyleIndex::GameCube: - vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; - break; - case Core::HID::NpadStyleIndex::N64: - vibration_device_info.type = Core::HID::VibrationDeviceType::N64; - break; - default: - vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; - break; - } - - vibration_device_info.position = Core::HID::VibrationDevicePosition::None; - if (check_device_index) { - switch (vibration_device_handle.device_index) { - case Core::HID::DeviceIndex::Left: - vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; - break; - case Core::HID::DeviceIndex::Right: - vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; - break; - case Core::HID::DeviceIndex::None: - default: - ASSERT_MSG(false, "DeviceIndex should never be None!"); - break; - } - } - LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", - vibration_device_info.type, vibration_device_info.position); - - const auto result = IsVibrationHandleValid(vibration_device_handle); - if (result.IsError()) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } + Core::HID::VibrationDeviceInfo vibration_device_info{}; + const auto result = GetResourceManager()->GetVibrationDeviceInfo(vibration_device_info, + vibration_device_handle); IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); + rb.Push(result); rb.PushRaw(vibration_device_info); } @@ -1560,16 +1545,16 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - GetResourceManager()->GetNpad()->VibrateController(parameters.applet_resource_user_id, - parameters.vibration_device_handle, - parameters.vibration_value); - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.vibration_device_handle.npad_type, parameters.vibration_device_handle.npad_id, parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + GetResourceManager()->SendVibrationValue(parameters.applet_resource_user_id, + parameters.vibration_device_handle, + parameters.vibration_value); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -1591,10 +1576,28 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) { parameters.vibration_device_handle.npad_id, parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + bool has_active_aruid{}; + NpadVibrationDevice* device{nullptr}; + Core::HID::VibrationValue vibration_value{}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + device = GetResourceManager()->GetNSVibrationDevice(parameters.vibration_device_handle); + } + if (device != nullptr) { + result = device->GetActualVibrationValue(vibration_value); + } + if (result.IsError()) { + vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; + } + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); - rb.PushRaw(GetResourceManager()->GetNpad()->GetLastVibration( - parameters.applet_resource_user_id, parameters.vibration_device_handle)); + rb.PushRaw(vibration_value); } void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { @@ -1609,25 +1612,27 @@ void IHidServer::PermitVibration(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_vibrate{rp.Pop<bool>()}; - // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value - // by converting it to a bool - Settings::values.vibration_enabled.SetValue(can_vibrate); - LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( + can_vibrate ? 1.0f : 0.0f); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called"); - // nnSDK checks if a float is greater than zero. We return the bool we stored earlier - const auto is_enabled = Settings::values.vibration_enabled.GetValue(); + f32 master_volume{}; + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( + master_volume); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(is_enabled); + rb.Push(result); + rb.Push(master_volume > 0.0f); } void IHidServer::SendVibrationValues(HLERequestContext& ctx) { @@ -1645,13 +1650,22 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) { auto vibration_values = std::span( reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); - GetResourceManager()->GetNpad()->VibrateControllers(applet_resource_user_id, - vibration_device_handles, vibration_values); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + Result result = ResultSuccess; + if (handle_count != vibration_count) { + result = ResultVibrationArraySizeMismatch; + } + + for (std::size_t i = 0; i < handle_count; i++) { + if (result.IsSuccess()) { + result = GetResourceManager()->SendVibrationValue( + applet_resource_user_id, vibration_device_handles[i], vibration_values[i]); + } + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { @@ -1666,43 +1680,6 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - /** - * Note: This uses yuzu-specific behavior such that the StopHard command produces - * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below, - * in order to differentiate between Stop and StopHard commands. - * This is done to reuse the controller vibration functions made for regular controllers. - */ - const auto vibration_value = [parameters] { - switch (parameters.gc_erm_command) { - case Core::HID::VibrationGcErmCommand::Stop: - return Core::HID::VibrationValue{ - .low_amplitude = 0.0f, - .low_frequency = 160.0f, - .high_amplitude = 0.0f, - .high_frequency = 320.0f, - }; - case Core::HID::VibrationGcErmCommand::Start: - return Core::HID::VibrationValue{ - .low_amplitude = 1.0f, - .low_frequency = 160.0f, - .high_amplitude = 1.0f, - .high_frequency = 320.0f, - }; - case Core::HID::VibrationGcErmCommand::StopHard: - return Core::HID::VibrationValue{ - .low_amplitude = 0.0f, - .low_frequency = 0.0f, - .high_amplitude = 0.0f, - .high_frequency = 0.0f, - }; - default: - return Core::HID::DEFAULT_VIBRATION_VALUE; - } - }(); - - GetResourceManager()->GetNpad()->VibrateController( - parameters.applet_resource_user_id, parameters.vibration_device_handle, vibration_value); - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " "gc_erm_command={}", @@ -1711,8 +1688,23 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, parameters.gc_erm_command); + bool has_active_aruid{}; + NpadGcVibrationDevice* gc_device{nullptr}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); + } + if (gc_device != nullptr) { + result = gc_device->SendVibrationGcErmCommand(parameters.gc_erm_command); + } + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { @@ -1725,33 +1717,31 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { const auto parameters{rp.PopRaw<Parameters>()}; - const auto last_vibration = GetResourceManager()->GetNpad()->GetLastVibration( - parameters.applet_resource_user_id, parameters.vibration_device_handle); - - const auto gc_erm_command = [last_vibration] { - if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { - return Core::HID::VibrationGcErmCommand::Start; - } - - /** - * Note: This uses yuzu-specific behavior such that the StopHard command produces - * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function - * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. - * This is done to reuse the controller vibration functions made for regular controllers. - */ - if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) { - return Core::HID::VibrationGcErmCommand::StopHard; - } - - return Core::HID::VibrationGcErmCommand::Stop; - }(); - LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", parameters.vibration_device_handle.npad_type, parameters.vibration_device_handle.npad_id, parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + bool has_active_aruid{}; + NpadGcVibrationDevice* gc_device{nullptr}; + Core::HID::VibrationGcErmCommand gc_erm_command{}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); + } + if (gc_device != nullptr) { + result = gc_device->GetActualVibrationGcErmCommand(gc_erm_command); + } + if (result.IsError()) { + gc_erm_command = Core::HID::VibrationGcErmCommand::Stop; + } + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.PushEnum(gc_erm_command); @@ -1761,21 +1751,24 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop<u64>()}; - GetResourceManager()->GetNpad()->SetPermitVibrationSession(true); - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( + applet_resource_user_id); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { - GetResourceManager()->GetNpad()->SetPermitVibrationSession(false); - LOG_DEBUG(Service_HID, "called"); + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); + IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + rb.Push(result); } void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { @@ -1795,10 +1788,61 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { parameters.vibration_device_handle.npad_id, parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); + bool is_mounted{}; + NpadVibrationBase* device{nullptr}; + Result result = IsVibrationHandleValid(parameters.vibration_device_handle); + + if (result.IsSuccess()) { + device = GetResourceManager()->GetVibrationDevice(parameters.vibration_device_handle); + } + + if (device != nullptr) { + is_mounted = device->IsVibrationMounted(); + } + IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted( - parameters.applet_resource_user_id, parameters.vibration_device_handle)); + rb.Push(result); + rb.Push(is_mounted); +} + +void IHidServer::SendVibrationValueInBool(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + Core::HID::VibrationDeviceHandle vibration_device_handle; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + bool is_vibrating; + }; + static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_DEBUG(Service_HID, + "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " + "is_vibrating={}", + parameters.vibration_device_handle.npad_type, + parameters.vibration_device_handle.npad_id, + parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, + parameters.is_vibrating); + + bool has_active_aruid{}; + NpadN64VibrationDevice* n64_device{nullptr}; + Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, + has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(parameters.vibration_device_handle); + } + if (result.IsSuccess() && has_active_aruid) { + n64_device = + GetResourceManager()->GetN64VibrationDevice(parameters.vibration_device_handle); + } + if (n64_device != nullptr) { + result = n64_device->SendValueInBool(parameters.is_vibrating); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); } void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index cc7c4ebdd..3a2e0a230 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h @@ -97,6 +97,7 @@ private: void BeginPermitVibrationSession(HLERequestContext& ctx); void EndPermitVibrationSession(HLERequestContext& ctx); void IsVibrationDeviceMounted(HLERequestContext& ctx); + void SendVibrationValueInBool(HLERequestContext& ctx); void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); void StartConsoleSixAxisSensor(HLERequestContext& ctx); void StopConsoleSixAxisSensor(HLERequestContext& ctx); diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 3a0cb3cb1..4466a189b 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -7,6 +7,7 @@ #include "hid_core/resource_manager.h" #include "hid_core/resources/npad/npad.h" #include "hid_core/resources/npad/npad_types.h" +#include "hid_core/resources/npad/npad_vibration.h" #include "hid_core/resources/palma/palma.h" #include "hid_core/resources/touch_screen/touch_screen.h" @@ -67,14 +68,14 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, - {504, nullptr, "SetAruidValidForVibration"}, + {504, &IHidSystemServer::SetAruidValidForVibration, "SetAruidValidForVibration"}, {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, - {510, nullptr, "SetVibrationMasterVolume"}, - {511, nullptr, "GetVibrationMasterVolume"}, - {512, nullptr, "BeginPermitVibrationSession"}, - {513, nullptr, "EndPermitVibrationSession"}, + {510, &IHidSystemServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"}, + {511, &IHidSystemServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"}, + {512, &IHidSystemServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, + {513, &IHidSystemServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, {514, nullptr, "Unknown514"}, {520, nullptr, "EnableHandheldHids"}, {521, nullptr, "DisableHandheldHids"}, @@ -156,7 +157,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, {1154, nullptr, "IsFirmwareAvailableForNotification"}, - {1155, nullptr, "SetForceHandheldStyleVibration"}, + {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"}, {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, {1157, nullptr, "CancelConnectionTrigger"}, {1200, nullptr, "IsButtonConfigSupported"}, @@ -538,6 +539,27 @@ void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void IHidSystemServer::SetAruidValidForVibration(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + struct Parameters { + bool is_enabled; + INSERT_PADDING_WORDS_NOINIT(1); + u64 applet_resource_user_id; + }; + static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); + + const auto parameters{rp.PopRaw<Parameters>()}; + + LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}", + parameters.is_enabled, parameters.applet_resource_user_id); + + GetResourceManager()->SetAruidValidForVibration(parameters.applet_resource_user_id, + parameters.is_enabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void IHidSystemServer::EnableAppletToGetSixAxisSensor(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; struct Parameters { @@ -601,6 +623,57 @@ void IHidSystemServer::EnableAppletToGetTouchScreen(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void IHidSystemServer::SetVibrationMasterVolume(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto master_volume{rp.Pop<f32>()}; + + LOG_INFO(Service_HID, "called, volume={}", master_volume); + + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( + master_volume); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IHidSystemServer::GetVibrationMasterVolume(HLERequestContext& ctx) { + f32 master_volume{}; + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( + master_volume); + + LOG_INFO(Service_HID, "called, volume={}", master_volume); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(result); + rb.Push(master_volume); +} + +void IHidSystemServer::BeginPermitVibrationSession(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); + + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IHidSystemServer::EndPermitVibrationSession(HLERequestContext& ctx) { + LOG_INFO(Service_HID, "called"); + + const auto result = + GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { const bool is_attached = true; @@ -749,6 +822,19 @@ void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx rb.PushRaw(touchscreen_config); } +void IHidSystemServer::SetForceHandheldStyleVibration(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto is_forced{rp.Pop<bool>()}; + + LOG_INFO(Service_HID, "called, is_forced={}", is_forced); + + GetResourceManager()->SetForceHandheldStyleVibration(is_forced); + GetResourceManager()->GetNpad()->UpdateHandheldAbstractState(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { const bool is_enabled = false; diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index 0c2634e3f..90a719f02 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h @@ -42,9 +42,14 @@ private: void RegisterAppletResourceUserId(HLERequestContext& ctx); void UnregisterAppletResourceUserId(HLERequestContext& ctx); void EnableAppletToGetInput(HLERequestContext& ctx); + void SetAruidValidForVibration(HLERequestContext& ctx); void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); void EnableAppletToGetPadInput(HLERequestContext& ctx); void EnableAppletToGetTouchScreen(HLERequestContext& ctx); + void SetVibrationMasterVolume(HLERequestContext& ctx); + void GetVibrationMasterVolume(HLERequestContext& ctx); + void BeginPermitVibrationSession(HLERequestContext& ctx); + void EndPermitVibrationSession(HLERequestContext& ctx); void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); @@ -61,6 +66,7 @@ private: void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); + void SetForceHandheldStyleVibration(HLERequestContext& ctx); void IsUsingCustomButtonConfig(HLERequestContext& ctx); std::shared_ptr<ResourceManager> GetResourceManager(); diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 0469110e8..af6591370 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -112,9 +112,7 @@ void Nvnflinger::ShutdownLayers() { { const auto lock_guard = Lock(); for (auto& display : displays) { - for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { - display.GetLayer(layer).GetConsumer().Abandon(); - } + display.Abandon(); } is_abandoned = true; @@ -176,24 +174,28 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { display.CreateLayer(layer_id, buffer_id, nvdrv->container); } -void Nvnflinger::OpenLayer(u64 layer_id) { +bool Nvnflinger::OpenLayer(u64 layer_id) { const auto lock_guard = Lock(); for (auto& display : displays) { if (auto* layer = display.FindLayer(layer_id); layer) { - layer->Open(); + return layer->Open(); } } + + return false; } -void Nvnflinger::CloseLayer(u64 layer_id) { +bool Nvnflinger::CloseLayer(u64 layer_id) { const auto lock_guard = Lock(); for (auto& display : displays) { if (auto* layer = display.FindLayer(layer_id); layer) { - layer->Close(); + return layer->Close(); } } + + return false; } void Nvnflinger::DestroyLayer(u64 layer_id) { diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 871285764..a60e0ae6b 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -74,10 +74,10 @@ public: [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); /// Opens a layer on all displays for the given layer ID. - void OpenLayer(u64 layer_id); + bool OpenLayer(u64 layer_id); /// Closes a layer on all displays for the given layer ID. - void CloseLayer(u64 layer_id); + bool CloseLayer(u64 layer_id); /// Destroys the given layer ID. void DestroyLayer(u64 layer_id); diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index e2d9cd98a..725311c53 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -91,6 +91,10 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id, layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, std::move(buffer_item_consumer))); + if (is_abandoned) { + this->FindLayer(layer_id)->GetConsumer().Abandon(); + } + hos_binder_driver_server.RegisterProducer(std::move(producer)); } @@ -103,6 +107,13 @@ void Display::DestroyLayer(u64 layer_id) { [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); } +void Display::Abandon() { + for (auto& layer : layers) { + layer->GetConsumer().Abandon(); + } + is_abandoned = true; +} + Layer* Display::FindLayer(u64 layer_id) { const auto itr = std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 7e68ee79b..8eb8a5155 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h @@ -98,6 +98,8 @@ public: layers.clear(); } + void Abandon(); + /// Attempts to find a layer with the given ID. /// /// @param layer_id The layer ID. @@ -124,6 +126,7 @@ private: std::vector<std::unique_ptr<Layer>> layers; Kernel::KEvent* vsync_event{}; + bool is_abandoned{}; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index 295005e23..f95e2dc71 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h @@ -4,6 +4,7 @@ #pragma once #include <memory> +#include <utility> #include "common/common_types.h" @@ -75,12 +76,12 @@ public: return open; } - void Close() { - open = false; + bool Close() { + return std::exchange(open, false); } - void Open() { - open = true; + bool Open() { + return !std::exchange(open, true); } private: diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 39d5be90d..bfcc27ddc 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -719,7 +719,12 @@ private: return; } - nvnflinger.OpenLayer(layer_id); + if (!nvnflinger.OpenLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to open layer which was already open"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultOperationFailed); + return; + } android::OutputParcel parcel; parcel.WriteInterface(NativeWindow{*buffer_queue_id}); @@ -737,7 +742,12 @@ private: LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); - nvnflinger.CloseLayer(layer_id); + if (!nvnflinger.CloseLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to close layer which was not open"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultOperationFailed); + return; + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); |