diff --git a/README.md b/README.md index 08d9243de..e5ac41798 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4069. +This is the source code for early-access 4070. ## Legal Notice diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 93c8ce922..9b08f008d 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -49,7 +49,6 @@ import org.yuzu.yuzu_emu.utils.ForegroundService import org.yuzu.yuzu_emu.utils.InputHandler import org.yuzu.yuzu_emu.utils.Log import org.yuzu.yuzu_emu.utils.MemoryUtil -import org.yuzu.yuzu_emu.utils.NativeConfig import org.yuzu.yuzu_emu.utils.NfcReader import org.yuzu.yuzu_emu.utils.ThemeHelper import java.text.NumberFormat @@ -171,11 +170,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { stopMotionSensorListener() } - override fun onStop() { - super.onStop() - NativeConfig.saveGlobalConfig() - } - override fun onUserLeaveHint() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 9efc1705d..47767454a 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -554,6 +554,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { findItem(R.id.menu_touchscreen).isChecked = BooleanSetting.TOUCHSCREEN.getBoolean() } + popup.setOnDismissListener { NativeConfig.saveGlobalConfig() } popup.setOnMenuItemClickListener { when (it.itemId) { R.id.menu_toggle_fps -> { @@ -720,7 +721,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.emulation_control_adjust) .setView(adjustBinding.root) - .setPositiveButton(android.R.string.ok, null) + .setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> + NativeConfig.saveGlobalConfig() + } .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int -> setControlScale(50) setControlOpacity(100) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4e5eaf2c3..490e5441e 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -716,22 +716,23 @@ add_library(core STATIC hle/service/server_manager.h hle/service/service.cpp hle/service/service.h - hle/service/set/appln_settings.cpp - hle/service/set/appln_settings.h - hle/service/set/device_settings.cpp - hle/service/set/device_settings.h + hle/service/set/setting_formats/appln_settings.cpp + hle/service/set/setting_formats/appln_settings.h + hle/service/set/setting_formats/device_settings.cpp + hle/service/set/setting_formats/device_settings.h + hle/service/set/setting_formats/system_settings.cpp + hle/service/set/setting_formats/system_settings.h + hle/service/set/setting_formats/private_settings.cpp + hle/service/set/setting_formats/private_settings.h hle/service/set/factory_settings_server.cpp hle/service/set/factory_settings_server.h hle/service/set/firmware_debug_settings_server.cpp hle/service/set/firmware_debug_settings_server.h - hle/service/set/private_settings.cpp - hle/service/set/private_settings.h hle/service/set/settings.cpp hle/service/set/settings.h hle/service/set/settings_server.cpp hle/service/set/settings_server.h - hle/service/set/system_settings.cpp - hle/service/set/system_settings.h + hle/service/set/settings_types.h hle/service/set/system_settings_server.cpp hle/service/set/system_settings_server.h hle/service/sm/sm.cpp diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index a2def33c3..1c9f5883b 100755 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -20,12 +20,13 @@ void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); std::shared_ptr resource_manager = std::make_shared(system); std::shared_ptr firmware_settings = - std::make_shared(); + std::make_shared(system); // TODO: Remove this hack when am is emulated properly. resource_manager->Initialize(); resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), true); + resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true); server_manager->RegisterNamedService( "hid", std::make_shared(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 100755 --- 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()}; - 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 vibration_device_list{}; std::shared_ptr resource_manager; }; @@ -153,7 +184,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr 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()}; - 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()}; - 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()}; - // 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(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()}; - /** - * 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()}; - 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()}; - 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()}; + + 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 100755 --- 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 100755 --- 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()}; + + 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()}; + + 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()}; + + 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()}; + + 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 100755 --- 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 GetResourceManager(); diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 31cc87acc..cc7776efc 100755 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -441,7 +441,10 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target device_state = DeviceState::TagMounted; mount_target = mount_target_; - if (!is_corrupted && mount_target != NFP::MountTarget::Rom) { + const bool create_backup = + mount_target == NFP::MountTarget::All || mount_target == NFP::MountTarget::Ram || + (mount_target == NFP::MountTarget::Rom && HasBackup(encrypted_tag_data.uuid).IsError()); + if (!is_corrupted && create_backup) { std::vector data(sizeof(NFP::EncryptedNTAG215File)); memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); WriteBackupData(encrypted_tag_data.uuid, data); diff --git a/src/core/hle/service/set/setting_formats/appln_settings.cpp b/src/core/hle/service/set/setting_formats/appln_settings.cpp new file mode 100755 index 000000000..f7c7d5b91 --- /dev/null +++ b/src/core/hle/service/set/setting_formats/appln_settings.cpp @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/set/setting_formats/appln_settings.h" + +namespace Service::Set { + +ApplnSettings DefaultApplnSettings() { + ApplnSettings settings{}; + + settings.mii_author_id = Common::UUID::MakeDefault(); + + return settings; +} + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/appln_settings.h b/src/core/hle/service/set/setting_formats/appln_settings.h new file mode 100755 index 000000000..ba9af998a --- /dev/null +++ b/src/core/hle/service/set/setting_formats/appln_settings.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "common/uuid.h" +#include "core/hle/service/set/settings_types.h" + +namespace Service::Set { +struct ApplnSettings { + INSERT_PADDING_BYTES(0x10); // Reserved + + // nn::util::Uuid MiiAuthorId, copied from system settings 0x94B0 + Common::UUID mii_author_id; + INSERT_PADDING_BYTES(0x30); // Reserved + + // nn::settings::system::ServiceDiscoveryControlSettings + u32 service_discovery_control_settings; + INSERT_PADDING_BYTES(0x20); // Reserved + + bool in_repair_process_enable_flag; + INSERT_PADDING_BYTES(0x3); +}; +static_assert(offsetof(ApplnSettings, mii_author_id) == 0x10); +static_assert(offsetof(ApplnSettings, service_discovery_control_settings) == 0x50); +static_assert(offsetof(ApplnSettings, in_repair_process_enable_flag) == 0x74); +static_assert(sizeof(ApplnSettings) == 0x78, "ApplnSettings has the wrong size!"); + +ApplnSettings DefaultApplnSettings(); + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/device_settings.cpp b/src/core/hle/service/set/setting_formats/device_settings.cpp new file mode 100755 index 000000000..5f295404d --- /dev/null +++ b/src/core/hle/service/set/setting_formats/device_settings.cpp @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/set/setting_formats/device_settings.h" + +namespace Service::Set { + +DeviceSettings DefaultDeviceSettings() { + return {}; +} + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/device_settings.h b/src/core/hle/service/set/setting_formats/device_settings.h new file mode 100755 index 000000000..2827756f6 --- /dev/null +++ b/src/core/hle/service/set/setting_formats/device_settings.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/common_types.h" +#include "common/vector_math.h" +#include "core/hle/service/set/settings_types.h" + +namespace Service::Set { +struct DeviceSettings { + INSERT_PADDING_BYTES(0x10); // Reserved + + // nn::settings::BatteryLot + std::array ptm_battery_lot; + // nn::settings::system::PtmFuelGaugeParameter + std::array ptm_fuel_gauge_parameter; + u8 ptm_battery_version; + // nn::settings::system::PtmCycleCountReliability + u32 ptm_cycle_count_reliability; + INSERT_PADDING_BYTES(0x48); // Reserved + + // nn::settings::system::AnalogStickUserCalibration L + std::array analog_user_stick_calibration_l; + // nn::settings::system::AnalogStickUserCalibration R + std::array analog_user_stick_calibration_r; + INSERT_PADDING_BYTES(0x20); // Reserved + + // nn::settings::system::ConsoleSixAxisSensorAccelerationBias + Common::Vec3 console_six_axis_sensor_acceleration_bias; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias + Common::Vec3 console_six_axis_sensor_angular_velocity_bias; + // nn::settings::system::ConsoleSixAxisSensorAccelerationGain + std::array console_six_axis_sensor_acceleration_gain; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain + std::array console_six_axis_sensor_angular_velocity_gain; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias + Common::Vec3 console_six_axis_sensor_angular_velocity_time_bias; + // nn::settings::system::ConsoleSixAxisSensorAngularAcceleration + std::array console_six_axis_sensor_angular_acceleration; +}; +static_assert(offsetof(DeviceSettings, ptm_battery_lot) == 0x10); +static_assert(offsetof(DeviceSettings, ptm_cycle_count_reliability) == 0x44); +static_assert(offsetof(DeviceSettings, analog_user_stick_calibration_l) == 0x90); +static_assert(offsetof(DeviceSettings, console_six_axis_sensor_acceleration_bias) == 0xD0); +static_assert(offsetof(DeviceSettings, console_six_axis_sensor_angular_acceleration) == 0x13C); +static_assert(sizeof(DeviceSettings) == 0x160, "DeviceSettings has the wrong size!"); + +DeviceSettings DefaultDeviceSettings(); + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/private_settings.cpp b/src/core/hle/service/set/setting_formats/private_settings.cpp new file mode 100755 index 000000000..81c362482 --- /dev/null +++ b/src/core/hle/service/set/setting_formats/private_settings.cpp @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/set/setting_formats/private_settings.h" + +namespace Service::Set { + +PrivateSettings DefaultPrivateSettings() { + return {}; +} + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/private_settings.h b/src/core/hle/service/set/setting_formats/private_settings.h new file mode 100755 index 000000000..6c40f62e1 --- /dev/null +++ b/src/core/hle/service/set/setting_formats/private_settings.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/common_types.h" +#include "common/uuid.h" +#include "core/hle/service/set/settings_types.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::Set { + +struct PrivateSettings { + INSERT_PADDING_BYTES(0x10); // Reserved + + InitialLaunchSettings initial_launch_settings; + INSERT_PADDING_BYTES(0x20); // Reserved + + Common::UUID external_clock_source_id; + s64 shutdown_rtc_value; + s64 external_steady_clock_internal_offset; + INSERT_PADDING_BYTES(0x60); // Reserved + + // nn::settings::system::PlatformRegion + s32 platform_region; + INSERT_PADDING_BYTES(0x4); // Reserved +}; +static_assert(offsetof(PrivateSettings, initial_launch_settings) == 0x10); +static_assert(offsetof(PrivateSettings, external_clock_source_id) == 0x50); +static_assert(offsetof(PrivateSettings, shutdown_rtc_value) == 0x60); +static_assert(offsetof(PrivateSettings, external_steady_clock_internal_offset) == 0x68); +static_assert(offsetof(PrivateSettings, platform_region) == 0xD0); +static_assert(sizeof(PrivateSettings) == 0xD8, "PrivateSettings has the wrong size!"); + +PrivateSettings DefaultPrivateSettings(); + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp new file mode 100755 index 000000000..66e57651e --- /dev/null +++ b/src/core/hle/service/set/setting_formats/system_settings.cpp @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/set/setting_formats/system_settings.h" + +namespace Service::Set { + +SystemSettings DefaultSystemSettings() { + SystemSettings settings{}; + + settings.version = 0x140000; + settings.flags = 7; + + settings.mii_author_id = Common::UUID::MakeDefault(); + + settings.color_set_id = ColorSet::BasicWhite; + + settings.notification_settings = { + .flags{0x300}, + .volume = NotificationVolume::High, + .start_time = {.hour = 9, .minute = 0}, + .stop_time = {.hour = 21, .minute = 0}, + }; + + settings.tv_settings = { + .flags = {0xC}, + .tv_resolution = TvResolution::Auto, + .hdmi_content_type = HdmiContentType::Game, + .rgb_range = RgbRange::Auto, + .cmu_mode = CmuMode::None, + .tv_underscan = {}, + .tv_gama = 1.0f, + .contrast_ratio = 0.5f, + }; + + settings.initial_launch_settings_packed = { + .flags = {0x10001}, + .timestamp = {}, + }; + + settings.sleep_settings = { + .flags = {0x3}, + .handheld_sleep_plan = HandheldSleepPlan::Sleep10Min, + .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, + }; + + settings.device_time_zone_location_name = {"UTC"}; + settings.user_system_clock_automatic_correction_enabled = false; + + settings.primary_album_storage = PrimaryAlbumStorage::SdCard; + settings.battery_percentage_flag = true; + settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0; + + return settings; +} + +} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h new file mode 100755 index 000000000..14654f8b1 --- /dev/null +++ b/src/core/hle/service/set/setting_formats/system_settings.h @@ -0,0 +1,389 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/uuid.h" +#include "common/vector_math.h" +#include "core/hle/service/set/setting_formats/private_settings.h" +#include "core/hle/service/set/settings_types.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::Set { + +struct SystemSettings { + // 0/unwritten (1.0.0), 0x20000 (2.0.0), 0x30000 (3.0.0-3.0.1), 0x40001 (4.0.0-4.1.0), 0x50000 + // (5.0.0-5.1.0), 0x60000 (6.0.0-6.2.0), 0x70000 (7.0.0), 0x80000 (8.0.0-8.1.1), 0x90000 + // (9.0.0-10.0.4), 0x100100 (10.1.0+), 0x120000 (12.0.0-12.1.0), 0x130000 (13.0.0-13.2.1), + // 0x140000 (14.0.0+) + u32 version; + // 0/unwritten (1.0.0), 1 (6.0.0-8.1.0), 2 (8.1.1), 7 (9.0.0+). + // if (flags & 2), defaults are written for AnalogStickUserCalibration + u32 flags; + INSERT_PADDING_BYTES(0x8); // Reserved + + LanguageCode language_code; + INSERT_PADDING_BYTES(0x38); // Reserved + + // nn::settings::system::NetworkSettings + u32 network_setting_count; + bool wireless_lan_enable_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x8); // Reserved + + // nn::settings::system::NetworkSettings + std::array, 32> network_settings_1B0; + + // nn::settings::system::BluetoothDevicesSettings + std::array bluetooth_device_settings_count; + bool bluetooth_enable_flag; + INSERT_PADDING_BYTES(0x3); + bool bluetooth_afh_enable_flag; + INSERT_PADDING_BYTES(0x3); + bool bluetooth_boost_enable_flag; + INSERT_PADDING_BYTES(0x3); + std::array, 10> bluetooth_device_settings_first_10; + + s32 ldn_channel; + INSERT_PADDING_BYTES(0x3C); // Reserved + + // nn::util::Uuid MiiAuthorId + Common::UUID mii_author_id; + + INSERT_PADDING_BYTES(0x30); // Reserved + + // nn::settings::system::NxControllerSettings + u32 nx_controller_settings_count; + + INSERT_PADDING_BYTES(0xC); // Reserved + + // nn::settings::system::NxControllerSettings, + // nn::settings::system::NxControllerLegacySettings on 13.0.0+ + std::array, 10> nx_controller_legacy_settings; + INSERT_PADDING_BYTES(0x170); // Reserved + + bool external_rtc_reset_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x3C); // Reserved + + s32 push_notification_activity_mode_on_sleep; + INSERT_PADDING_BYTES(0x3C); // Reserved + + ErrorReportSharePermission error_report_share_permission; + INSERT_PADDING_BYTES(0x3C); // Reserved + + KeyboardLayout keyboard_layout; + INSERT_PADDING_BYTES(0x3C); // Reserved + + bool web_inspector_flag; + INSERT_PADDING_BYTES(0x3); + + // nn::settings::system::AllowedSslHost + u32 allowed_ssl_host_count; + + bool memory_usage_rate_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x34); // Reserved + + // nn::settings::system::HostFsMountPoint + std::array host_fs_mount_point; + + // nn::settings::system::AllowedSslHost + std::array, 8> allowed_ssl_hosts; + INSERT_PADDING_BYTES(0x6C0); // Reserved + + // nn::settings::system::BlePairingSettings + u32 ble_pairing_settings_count; + INSERT_PADDING_BYTES(0xC); // Reserved + std::array, 10> ble_pairing_settings; + + // nn::settings::system::AccountOnlineStorageSettings + u32 account_online_storage_settings_count; + INSERT_PADDING_BYTES(0xC); // Reserved + std::array, 8> account_online_storage_settings; + + bool pctl_ready_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x3C); // Reserved + + // nn::settings::system::ThemeId + std::array theme_id_type0; + std::array theme_id_type1; + INSERT_PADDING_BYTES(0x100); // Reserved + + ChineseTraditionalInputMethod chinese_traditional_input_method; + INSERT_PADDING_BYTES(0x3C); // Reserved + + bool zoom_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x3C); // Reserved + + // nn::settings::system::ButtonConfigRegisteredSettings + u32 button_config_registered_settings_count; + INSERT_PADDING_BYTES(0xC); // Reserved + + // nn::settings::system::ButtonConfigSettings + u32 button_config_settings_count; + INSERT_PADDING_BYTES(0x4); // Reserved + std::array, 5> button_config_settings; + INSERT_PADDING_BYTES(0x13B0); // Reserved + u32 button_config_settings_embedded_count; + INSERT_PADDING_BYTES(0x4); // Reserved + std::array, 5> button_config_settings_embedded; + INSERT_PADDING_BYTES(0x13B0); // Reserved + u32 button_config_settings_left_count; + INSERT_PADDING_BYTES(0x4); // Reserved + std::array, 5> button_config_settings_left; + INSERT_PADDING_BYTES(0x13B0); // Reserved + u32 button_config_settings_right_count; + INSERT_PADDING_BYTES(0x4); // Reserved + std::array, 5> button_config_settings_right; + INSERT_PADDING_BYTES(0x73B0); // Reserved + // nn::settings::system::ButtonConfigRegisteredSettings + std::array button_config_registered_settings_embedded; + std::array, 10> button_config_registered_settings; + INSERT_PADDING_BYTES(0x7FF8); // Reserved + + // nn::settings::system::ConsoleSixAxisSensorAccelerationBias + Common::Vec3 console_six_axis_sensor_acceleration_bias; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias + Common::Vec3 console_six_axis_sensor_angular_velocity_bias; + // nn::settings::system::ConsoleSixAxisSensorAccelerationGain + std::array console_six_axis_sensor_acceleration_gain; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain + std::array console_six_axis_sensor_angular_velocity_gain; + // nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias + Common::Vec3 console_six_axis_sensor_angular_velocity_time_bias; + // nn::settings::system::ConsoleSixAxisSensorAngularAcceleration + std::array console_six_axis_sensor_angular_velocity_acceleration; + INSERT_PADDING_BYTES(0x70); // Reserved + + bool lock_screen_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x4); // Reserved + + ColorSet color_set_id; + + QuestFlag quest_flag; + + SystemRegionCode region_code; + + // Different to nn::settings::system::InitialLaunchSettings? + InitialLaunchSettingsPacked initial_launch_settings_packed; + + bool battery_percentage_flag; + INSERT_PADDING_BYTES(0x3); + + // BitFlagSet<32, nn::settings::system::AppletLaunchFlag> + u32 applet_launch_flag; + + // nn::settings::system::ThemeSettings + std::array theme_settings; + // nn::fssystem::ArchiveMacKey + std::array theme_key; + + bool field_testing_flag; + INSERT_PADDING_BYTES(0x3); + + s32 panel_crc_mode; + INSERT_PADDING_BYTES(0x28); // Reserved + + // nn::settings::system::BacklightSettings + std::array backlight_settings_mixed_up; + INSERT_PADDING_BYTES(0x64); // Reserved + + Service::Time::Clock::SystemClockContext user_system_clock_context; + Service::Time::Clock::SystemClockContext network_system_clock_context; + bool user_system_clock_automatic_correction_enabled; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x4); // Reserved + Service::Time::Clock::SteadyClockTimePoint + user_system_clock_automatic_correction_updated_time_point; + INSERT_PADDING_BYTES(0x10); // Reserved + + AccountSettings account_settings; + INSERT_PADDING_BYTES(0xFC); // Reserved + + // nn::settings::system::AudioVolume + std::array audio_volume_type0; + std::array audio_volume_type1; + // nn::settings::system::AudioOutputMode + s32 audio_output_mode_type0; + s32 audio_output_mode_type1; + s32 audio_output_mode_type2; + bool force_mute_on_headphone_removed; + INSERT_PADDING_BYTES(0x3); + s32 headphone_volume_warning_count; + bool heaphone_volume_update_flag; + INSERT_PADDING_BYTES(0x3); + // nn::settings::system::AudioVolume + std::array audio_volume_type2; + // nn::settings::system::AudioOutputMode + s32 audio_output_mode_type3; + s32 audio_output_mode_type4; + bool hearing_protection_safeguard_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x4); // Reserved + s64 hearing_protection_safeguard_remaining_time; + INSERT_PADDING_BYTES(0x38); // Reserved + + bool console_information_upload_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x3C); // Reserved + + bool automatic_application_download_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x4); // Reserved + + NotificationSettings notification_settings; + INSERT_PADDING_BYTES(0x60); // Reserved + + // nn::settings::system::AccountNotificationSettings + u32 account_notification_settings_count; + INSERT_PADDING_BYTES(0xC); // Reserved + std::array account_notification_settings; + INSERT_PADDING_BYTES(0x140); // Reserved + + f32 vibration_master_volume; + + bool usb_full_key_enable_flag; + INSERT_PADDING_BYTES(0x3); + + // nn::settings::system::AnalogStickUserCalibration + std::array analog_stick_user_calibration_left; + std::array analog_stick_user_calibration_right; + + // nn::settings::system::TouchScreenMode + s32 touch_screen_mode; + INSERT_PADDING_BYTES(0x14); // Reserved + + TvSettings tv_settings; + + // nn::settings::system::Edid + std::array edid; + INSERT_PADDING_BYTES(0x2E0); // Reserved + + // nn::settings::system::DataDeletionSettings + std::array data_deletion_settings; + INSERT_PADDING_BYTES(0x38); // Reserved + + // nn::ncm::ProgramId + std::array initial_system_applet_program_id; + std::array overlay_disp_program_id; + INSERT_PADDING_BYTES(0x4); // Reserved + + bool requires_run_repair_time_reviser; + INSERT_PADDING_BYTES(0x6B); // Reserved + + Service::Time::TimeZone::LocationName device_time_zone_location_name; + INSERT_PADDING_BYTES(0x4); // Reserved + Service::Time::Clock::SteadyClockTimePoint device_time_zone_location_updated_time; + INSERT_PADDING_BYTES(0xC0); // Reserved + + // nn::settings::system::PrimaryAlbumStorage + PrimaryAlbumStorage primary_album_storage; + INSERT_PADDING_BYTES(0x3C); // Reserved + + bool usb_30_enable_flag; + INSERT_PADDING_BYTES(0x3); + bool usb_30_host_enable_flag; + INSERT_PADDING_BYTES(0x3); + bool usb_30_device_enable_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x34); // Reserved + + bool nfc_enable_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x3C); // Reserved + + // nn::settings::system::SleepSettings + SleepSettings sleep_settings; + INSERT_PADDING_BYTES(0x34); // Reserved + + // nn::settings::system::EulaVersion + u32 eula_version_count; + INSERT_PADDING_BYTES(0xC); // Reserved + std::array eula_versions; + INSERT_PADDING_BYTES(0x200); // Reserved + + // nn::settings::system::DeviceNickName + std::array device_nick_name; + INSERT_PADDING_BYTES(0x80); // Reserved + + bool auto_update_enable_flag; + INSERT_PADDING_BYTES(0x3); + INSERT_PADDING_BYTES(0x4C); // Reserved + + // nn::settings::system::BluetoothDevicesSettings + std::array, 14> bluetooth_device_settings_last_14; + INSERT_PADDING_BYTES(0x2000); // Reserved + + // nn::settings::system::NxControllerSettings + std::array, 10> nx_controller_settings_data_from_offset_30; +}; + +static_assert(offsetof(SystemSettings, language_code) == 0x10); +static_assert(offsetof(SystemSettings, network_setting_count) == 0x50); +static_assert(offsetof(SystemSettings, network_settings_1B0) == 0x60); +static_assert(offsetof(SystemSettings, bluetooth_device_settings_count) == 0x8060); +static_assert(offsetof(SystemSettings, bluetooth_enable_flag) == 0x8064); +static_assert(offsetof(SystemSettings, bluetooth_device_settings_first_10) == 0x8070); +static_assert(offsetof(SystemSettings, ldn_channel) == 0x9470); +static_assert(offsetof(SystemSettings, mii_author_id) == 0x94B0); +static_assert(offsetof(SystemSettings, nx_controller_settings_count) == 0x94F0); +static_assert(offsetof(SystemSettings, nx_controller_legacy_settings) == 0x9500); +static_assert(offsetof(SystemSettings, external_rtc_reset_flag) == 0x98F0); +static_assert(offsetof(SystemSettings, push_notification_activity_mode_on_sleep) == 0x9930); +static_assert(offsetof(SystemSettings, allowed_ssl_host_count) == 0x99F4); +static_assert(offsetof(SystemSettings, host_fs_mount_point) == 0x9A30); +static_assert(offsetof(SystemSettings, allowed_ssl_hosts) == 0x9B30); +static_assert(offsetof(SystemSettings, ble_pairing_settings_count) == 0xA9F0); +static_assert(offsetof(SystemSettings, ble_pairing_settings) == 0xAA00); +static_assert(offsetof(SystemSettings, account_online_storage_settings_count) == 0xAF00); +static_assert(offsetof(SystemSettings, account_online_storage_settings) == 0xAF10); +static_assert(offsetof(SystemSettings, pctl_ready_flag) == 0xB110); +static_assert(offsetof(SystemSettings, theme_id_type0) == 0xB150); +static_assert(offsetof(SystemSettings, chinese_traditional_input_method) == 0xB350); +static_assert(offsetof(SystemSettings, button_config_registered_settings_count) == 0xB3D0); +static_assert(offsetof(SystemSettings, button_config_settings_count) == 0xB3E0); +static_assert(offsetof(SystemSettings, button_config_settings) == 0xB3E8); +static_assert(offsetof(SystemSettings, button_config_registered_settings_embedded) == 0x1D3E0); +static_assert(offsetof(SystemSettings, console_six_axis_sensor_acceleration_bias) == 0x29370); +static_assert(offsetof(SystemSettings, lock_screen_flag) == 0x29470); +static_assert(offsetof(SystemSettings, battery_percentage_flag) == 0x294A0); +static_assert(offsetof(SystemSettings, field_testing_flag) == 0x294C0); +static_assert(offsetof(SystemSettings, backlight_settings_mixed_up) == 0x294F0); +static_assert(offsetof(SystemSettings, user_system_clock_context) == 0x29580); +static_assert(offsetof(SystemSettings, network_system_clock_context) == 0x295A0); +static_assert(offsetof(SystemSettings, user_system_clock_automatic_correction_enabled) == 0x295C0); +static_assert(offsetof(SystemSettings, user_system_clock_automatic_correction_updated_time_point) == + 0x295C8); +static_assert(offsetof(SystemSettings, account_settings) == 0x295F0); +static_assert(offsetof(SystemSettings, audio_volume_type0) == 0x296F0); +static_assert(offsetof(SystemSettings, hearing_protection_safeguard_remaining_time) == 0x29730); +static_assert(offsetof(SystemSettings, automatic_application_download_flag) == 0x297B0); +static_assert(offsetof(SystemSettings, notification_settings) == 0x297B8); +static_assert(offsetof(SystemSettings, account_notification_settings) == 0x29840); +static_assert(offsetof(SystemSettings, vibration_master_volume) == 0x29A40); +static_assert(offsetof(SystemSettings, analog_stick_user_calibration_left) == 0x29A48); +static_assert(offsetof(SystemSettings, touch_screen_mode) == 0x29A68); +static_assert(offsetof(SystemSettings, edid) == 0x29AA0); +static_assert(offsetof(SystemSettings, data_deletion_settings) == 0x29E80); +static_assert(offsetof(SystemSettings, requires_run_repair_time_reviser) == 0x29ED4); +static_assert(offsetof(SystemSettings, device_time_zone_location_name) == 0x29F40); +static_assert(offsetof(SystemSettings, nfc_enable_flag) == 0x2A0C0); +static_assert(offsetof(SystemSettings, eula_version_count) == 0x2A140); +static_assert(offsetof(SystemSettings, device_nick_name) == 0x2A950); +static_assert(offsetof(SystemSettings, bluetooth_device_settings_last_14) == 0x2AAA0); +static_assert(offsetof(SystemSettings, nx_controller_settings_data_from_offset_30) == 0x2E6A0); + +static_assert(sizeof(SystemSettings) == 0x336A0, "SystemSettings has the wrong size!"); + +SystemSettings DefaultSystemSettings(); + +} // namespace Service::Set diff --git a/src/core/hle/service/set/settings_server.h b/src/core/hle/service/set/settings_server.h index a4e78db6c..8304e8424 100755 --- a/src/core/hle/service/set/settings_server.h +++ b/src/core/hle/service/set/settings_server.h @@ -4,72 +4,13 @@ #pragma once #include "core/hle/service/service.h" -#include "core/hle/service/set/system_settings.h" +#include "core/hle/service/set/settings_types.h" namespace Core { class System; } namespace Service::Set { -enum class KeyboardLayout : u64 { - Japanese = 0, - EnglishUs = 1, - EnglishUsInternational = 2, - EnglishUk = 3, - French = 4, - FrenchCa = 5, - Spanish = 6, - SpanishLatin = 7, - German = 8, - Italian = 9, - Portuguese = 10, - Russian = 11, - Korean = 12, - ChineseSimplified = 13, - ChineseTraditional = 14, -}; - -constexpr std::array available_language_codes = {{ - LanguageCode::JA, - LanguageCode::EN_US, - LanguageCode::FR, - LanguageCode::DE, - LanguageCode::IT, - LanguageCode::ES, - LanguageCode::ZH_CN, - LanguageCode::KO, - LanguageCode::NL, - LanguageCode::PT, - LanguageCode::RU, - LanguageCode::ZH_TW, - LanguageCode::EN_GB, - LanguageCode::FR_CA, - LanguageCode::ES_419, - LanguageCode::ZH_HANS, - LanguageCode::ZH_HANT, - LanguageCode::PT_BR, -}}; - -static constexpr std::array, 18> language_to_layout{{ - {LanguageCode::JA, KeyboardLayout::Japanese}, - {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, - {LanguageCode::FR, KeyboardLayout::French}, - {LanguageCode::DE, KeyboardLayout::German}, - {LanguageCode::IT, KeyboardLayout::Italian}, - {LanguageCode::ES, KeyboardLayout::Spanish}, - {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, - {LanguageCode::KO, KeyboardLayout::Korean}, - {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, - {LanguageCode::PT, KeyboardLayout::Portuguese}, - {LanguageCode::RU, KeyboardLayout::Russian}, - {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, - {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, - {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, - {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, - {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, - {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, - {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, -}}; LanguageCode GetLanguageCodeFromIndex(std::size_t idx); diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h new file mode 100755 index 000000000..4dee202d7 --- /dev/null +++ b/src/core/hle/service/set/settings_types.h @@ -0,0 +1,451 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/uuid.h" +#include "core/hle/service/time/clock_types.h" + +namespace Service::Set { + +/// This is nn::settings::system::AudioOutputMode +enum class AudioOutputMode : u32 { + ch_1, + ch_2, + ch_5_1, + ch_7_1, +}; + +/// This is nn::settings::system::AudioOutputModeTarget +enum class AudioOutputModeTarget : u32 { + Hdmi, + Speaker, + Headphone, +}; + +/// This is nn::settings::system::AudioVolumeTarget +enum class AudioVolumeTarget : u32 { + Speaker, + Headphone, +}; + +/// This is nn::settings::system::ClockSourceId +enum class ClockSourceId : u32 { + NetworkSystemClock, + SteadyClock, +}; + +/// This is nn::settings::system::CmuMode +enum class CmuMode : u32 { + None, + ColorInvert, + HighContrast, + GrayScale, +}; + +/// This is nn::settings::system::ChineseTraditionalInputMethod +enum class ChineseTraditionalInputMethod : u32 { + Unknown0 = 0, + Unknown1 = 1, + Unknown2 = 2, +}; + +/// Indicates the current theme set by the system settings +enum class ColorSet : u32 { + BasicWhite = 0, + BasicBlack = 1, +}; + +/// This is nn::settings::system::ConsoleSleepPlan +enum class ConsoleSleepPlan : u32 { + Sleep1Hour, + Sleep2Hour, + Sleep3Hour, + Sleep6Hour, + Sleep12Hour, + Never, +}; + +/// This is nn::settings::system::ErrorReportSharePermission +enum class ErrorReportSharePermission : u32 { + NotConfirmed, + Granted, + Denied, +}; + +/// This is nn::settings::system::EulaVersionClockType +enum class EulaVersionClockType : u32 { + NetworkSystemClock, + SteadyClock, +}; + +/// This is nn::settings::factory::RegionCode +enum class FactoryRegionCode : u32 { + Japan, + Usa, + Europe, + Australia, + China, + Korea, + Taiwan, +}; + +/// This is nn::settings::system::FriendPresenceOverlayPermission +enum class FriendPresenceOverlayPermission : u8 { + NotConfirmed, + NoDisplay, + FavoriteFriends, + Friends, +}; + +enum class GetFirmwareVersionType { + Version1, + Version2, +}; + +/// This is nn::settings::system::HandheldSleepPlan +enum class HandheldSleepPlan : u32 { + Sleep1Min, + Sleep3Min, + Sleep5Min, + Sleep10Min, + Sleep30Min, + Never, +}; + +/// This is nn::settings::system::HdmiContentType +enum class HdmiContentType : u32 { + None, + Graphics, + Cinema, + Photo, + Game, +}; + +enum class KeyboardLayout : u32 { + Japanese = 0, + EnglishUs = 1, + EnglishUsInternational = 2, + EnglishUk = 3, + French = 4, + FrenchCa = 5, + Spanish = 6, + SpanishLatin = 7, + German = 8, + Italian = 9, + Portuguese = 10, + Russian = 11, + Korean = 12, + ChineseSimplified = 13, + ChineseTraditional = 14, +}; + +/// This is "nn::settings::LanguageCode", which is a NUL-terminated string stored in a u64. +enum class LanguageCode : u64 { + JA = 0x000000000000616A, + EN_US = 0x00000053552D6E65, + FR = 0x0000000000007266, + DE = 0x0000000000006564, + IT = 0x0000000000007469, + ES = 0x0000000000007365, + ZH_CN = 0x0000004E432D687A, + KO = 0x0000000000006F6B, + NL = 0x0000000000006C6E, + PT = 0x0000000000007470, + RU = 0x0000000000007572, + ZH_TW = 0x00000057542D687A, + EN_GB = 0x00000042472D6E65, + FR_CA = 0x00000041432D7266, + ES_419 = 0x00003931342D7365, + ZH_HANS = 0x00736E61482D687A, + ZH_HANT = 0x00746E61482D687A, + PT_BR = 0x00000052422D7470, +}; + +/// This is nn::settings::system::NotificationVolume +enum class NotificationVolume : u32 { + Mute, + Low, + High, +}; + +/// This is nn::settings::system::PrimaryAlbumStorage +enum class PrimaryAlbumStorage : u32 { + Nand, + SdCard, +}; + +/// Indicates the current console is a retail or kiosk unit +enum class QuestFlag : u8 { + Retail = 0, + Kiosk = 1, +}; + +/// This is nn::settings::system::RgbRange +enum class RgbRange : u32 { + Auto, + Full, + Limited, +}; + +/// This is nn::settings::system::RegionCode +enum class SystemRegionCode : u32 { + Japan, + Usa, + Europe, + Australia, + HongKongTaiwanKorea, + China, +}; + +/// This is nn::settings::system::TouchScreenMode +enum class TouchScreenMode : u32 { + Stylus, + Standard, +}; + +/// This is nn::settings::system::TvResolution +enum class TvResolution : u32 { + Auto, + Resolution1080p, + Resolution720p, + Resolution480p, +}; + +constexpr std::array available_language_codes = {{ + LanguageCode::JA, + LanguageCode::EN_US, + LanguageCode::FR, + LanguageCode::DE, + LanguageCode::IT, + LanguageCode::ES, + LanguageCode::ZH_CN, + LanguageCode::KO, + LanguageCode::NL, + LanguageCode::PT, + LanguageCode::RU, + LanguageCode::ZH_TW, + LanguageCode::EN_GB, + LanguageCode::FR_CA, + LanguageCode::ES_419, + LanguageCode::ZH_HANS, + LanguageCode::ZH_HANT, + LanguageCode::PT_BR, +}}; + +static constexpr std::array, 18> language_to_layout{{ + {LanguageCode::JA, KeyboardLayout::Japanese}, + {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, + {LanguageCode::FR, KeyboardLayout::French}, + {LanguageCode::DE, KeyboardLayout::German}, + {LanguageCode::IT, KeyboardLayout::Italian}, + {LanguageCode::ES, KeyboardLayout::Spanish}, + {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, + {LanguageCode::KO, KeyboardLayout::Korean}, + {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, + {LanguageCode::PT, KeyboardLayout::Portuguese}, + {LanguageCode::RU, KeyboardLayout::Russian}, + {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, + {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, + {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, + {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, + {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, + {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, + {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, +}}; + +/// This is nn::settings::system::AccountNotificationFlag +struct AccountNotificationFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> FriendOnlineFlag; + BitField<1, 1, u32> FriendRequestFlag; + BitField<8, 1, u32> CoralInvitationFlag; + }; +}; +static_assert(sizeof(AccountNotificationFlag) == 4, "AccountNotificationFlag is an invalid size"); + +/// This is nn::settings::system::AccountSettings +struct AccountSettings { + u32 flags; +}; +static_assert(sizeof(AccountSettings) == 4, "AccountSettings is an invalid size"); + +/// This is nn::settings::system::DataDeletionFlag +struct DataDeletionFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> AutomaticDeletionFlag; + }; +}; +static_assert(sizeof(DataDeletionFlag) == 4, "DataDeletionFlag is an invalid size"); + +/// This is nn::settings::system::InitialLaunchFlag +struct InitialLaunchFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> InitialLaunchCompletionFlag; + BitField<8, 1, u32> InitialLaunchUserAdditionFlag; + BitField<16, 1, u32> InitialLaunchTimestampFlag; + }; +}; +static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size"); + +/// This is nn::settings::system::SleepFlag +struct SleepFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> SleepsWhilePlayingMedia; + BitField<1, 1, u32> WakesAtPowerStateChange; + }; +}; +static_assert(sizeof(SleepFlag) == 4, "TvFlag is an invalid size"); + +/// This is nn::settings::system::NotificationFlag +struct NotificationFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> RingtoneFlag; + BitField<1, 1, u32> DownloadCompletionFlag; + BitField<8, 1, u32> EnablesNews; + BitField<9, 1, u32> IncomingLampFlag; + }; +}; +static_assert(sizeof(NotificationFlag) == 4, "NotificationFlag is an invalid size"); + +/// This is nn::settings::system::TvFlag +struct TvFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> Allows4k; + BitField<1, 1, u32> Allows3d; + BitField<2, 1, u32> AllowsCec; + BitField<3, 1, u32> PreventsScreenBurnIn; + }; +}; +static_assert(sizeof(TvFlag) == 4, "TvFlag is an invalid size"); + +/// This is nn::settings::system::UserSelectorFlag +struct UserSelectorFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> SkipIfSingleUser; + BitField<31, 1, u32> Unknown; + }; +}; +static_assert(sizeof(UserSelectorFlag) == 4, "UserSelectorFlag is an invalid size"); + +/// This is nn::settings::system::AccountNotificationSettings +struct AccountNotificationSettings { + Common::UUID uid; + AccountNotificationFlag flags; + FriendPresenceOverlayPermission friend_presence_permission; + FriendPresenceOverlayPermission friend_invitation_permission; + INSERT_PADDING_BYTES(0x2); +}; +static_assert(sizeof(AccountNotificationSettings) == 0x18, + "AccountNotificationSettings is an invalid size"); + +/// This is nn::settings::system::EulaVersion +struct EulaVersion { + u32 version; + SystemRegionCode region_code; + EulaVersionClockType clock_type; + INSERT_PADDING_BYTES(0x4); + s64 posix_time; + Time::Clock::SteadyClockTimePoint timestamp; +}; +static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size"); + +struct FirmwareVersionFormat { + u8 major; + u8 minor; + u8 micro; + INSERT_PADDING_BYTES(1); + u8 revision_major; + u8 revision_minor; + INSERT_PADDING_BYTES(2); + std::array platform; + std::array version_hash; + std::array display_version; + std::array display_title; +}; +static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size"); + +/// This is nn::settings::system::HomeMenuScheme +struct HomeMenuScheme { + u32 main; + u32 back; + u32 sub; + u32 bezel; + u32 extra; +}; +static_assert(sizeof(HomeMenuScheme) == 0x14, "HomeMenuScheme is incorrect size"); + +/// This is nn::settings::system::InitialLaunchSettings +struct InitialLaunchSettings { + InitialLaunchFlag flags; + INSERT_PADDING_BYTES(0x4); + Service::Time::Clock::SteadyClockTimePoint timestamp; +}; +static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size"); + +#pragma pack(push, 4) +struct InitialLaunchSettingsPacked { + InitialLaunchFlag flags; + Service::Time::Clock::SteadyClockTimePoint timestamp; +}; +#pragma pack(pop) +static_assert(sizeof(InitialLaunchSettingsPacked) == 0x1C, + "InitialLaunchSettingsPacked is incorrect size"); + +/// This is nn::settings::system::NotificationTime +struct NotificationTime { + u32 hour; + u32 minute; +}; +static_assert(sizeof(NotificationTime) == 0x8, "NotificationTime is an invalid size"); + +/// This is nn::settings::system::NotificationSettings +struct NotificationSettings { + NotificationFlag flags; + NotificationVolume volume; + NotificationTime start_time; + NotificationTime stop_time; +}; +static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); + +/// This is nn::settings::system::SleepSettings +struct SleepSettings { + SleepFlag flags; + HandheldSleepPlan handheld_sleep_plan; + ConsoleSleepPlan console_sleep_plan; +}; +static_assert(sizeof(SleepSettings) == 0xc, "SleepSettings is incorrect size"); + +/// This is nn::settings::system::TvSettings +struct TvSettings { + TvFlag flags; + TvResolution tv_resolution; + HdmiContentType hdmi_content_type; + RgbRange rgb_range; + CmuMode cmu_mode; + u32 tv_underscan; + f32 tv_gama; + f32 contrast_ratio; +}; +static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size"); + +} // namespace Service::Set diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index af9348522..87242ae68 100755 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -97,8 +97,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {3, &ISystemSettingsServer::GetFirmwareVersion, "GetFirmwareVersion"}, {4, &ISystemSettingsServer::GetFirmwareVersion2, "GetFirmwareVersion2"}, {5, nullptr, "GetFirmwareVersionDigest"}, - {7, nullptr, "GetLockScreenFlag"}, - {8, nullptr, "SetLockScreenFlag"}, + {7, &ISystemSettingsServer::GetLockScreenFlag, "GetLockScreenFlag"}, + {8, &ISystemSettingsServer::SetLockScreenFlag, "SetLockScreenFlag"}, {9, nullptr, "GetBacklightSettings"}, {10, nullptr, "SetBacklightSettings"}, {11, nullptr, "SetBluetoothDevicesSettings"}, @@ -157,12 +157,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {66, nullptr, "SetUsb30EnableFlag"}, {67, nullptr, "GetBatteryLot"}, {68, nullptr, "GetSerialNumber"}, - {69, nullptr, "GetNfcEnableFlag"}, - {70, nullptr, "SetNfcEnableFlag"}, + {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"}, + {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"}, {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"}, {72, &ISystemSettingsServer::SetSleepSettings, "SetSleepSettings"}, - {73, nullptr, "GetWirelessLanEnableFlag"}, - {74, nullptr, "SetWirelessLanEnableFlag"}, + {73, &ISystemSettingsServer::GetWirelessLanEnableFlag, "GetWirelessLanEnableFlag"}, + {74, &ISystemSettingsServer::SetWirelessLanEnableFlag, "SetWirelessLanEnableFlag"}, {75, &ISystemSettingsServer::GetInitialLaunchSettings, "GetInitialLaunchSettings"}, {76, &ISystemSettingsServer::SetInitialLaunchSettings, "SetInitialLaunchSettings"}, {77, &ISystemSettingsServer::GetDeviceNickName, "GetDeviceNickName"}, @@ -176,8 +176,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {85, nullptr, "SetPtmBatteryLot"}, {86, nullptr, "GetPtmFuelGaugeParameter"}, {87, nullptr, "SetPtmFuelGaugeParameter"}, - {88, nullptr, "GetBluetoothEnableFlag"}, - {89, nullptr, "SetBluetoothEnableFlag"}, + {88, &ISystemSettingsServer::GetBluetoothEnableFlag, "GetBluetoothEnableFlag"}, + {89, &ISystemSettingsServer::SetBluetoothEnableFlag, "SetBluetoothEnableFlag"}, {90, &ISystemSettingsServer::GetMiiAuthorId, "GetMiiAuthorId"}, {91, nullptr, "SetShutdownRtcValue"}, {92, nullptr, "GetShutdownRtcValue"}, @@ -510,6 +510,25 @@ void ISystemSettingsServer::SetUserSystemClockContext(HLERequestContext& ctx) { rb.Push(res); } +void ISystemSettingsServer::GetLockScreenFlag(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.lock_screen_flag); +} + +void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.lock_screen_flag = rp.Pop(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::GetAccountSettings(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called"); @@ -531,7 +550,7 @@ void ISystemSettingsServer::SetAccountSettings(HLERequestContext& ctx) { } void ISystemSettingsServer::GetEulaVersions(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, "called, elements={}", m_system_settings.eula_version_count); ctx.WriteBuffer(m_system_settings.eula_versions); @@ -557,7 +576,7 @@ void ISystemSettingsServer::SetEulaVersions(HLERequestContext& ctx) { } void ISystemSettingsServer::GetColorSetId(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called"); + LOG_DEBUG(Service_SET, "called, color_set=", m_system_settings.color_set_id); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -576,7 +595,13 @@ void ISystemSettingsServer::SetColorSetId(HLERequestContext& ctx) { } void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}", + m_system_settings.notification_settings.flags.raw, + m_system_settings.notification_settings.volume, + m_system_settings.notification_settings.start_time.hour, + m_system_settings.notification_settings.start_time.minute, + m_system_settings.notification_settings.stop_time.hour, + m_system_settings.notification_settings.stop_time.minute); IPC::ResponseBuilder rb{ctx, 8}; rb.Push(ResultSuccess); @@ -601,7 +626,8 @@ void ISystemSettingsServer::SetNotificationSettings(HLERequestContext& ctx) { } void ISystemSettingsServer::GetAccountNotificationSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, "called, elements={}", + m_system_settings.account_notification_settings_count); ctx.WriteBuffer(m_system_settings.account_notification_settings); @@ -645,6 +671,7 @@ using Settings = static Settings GetSettings() { Settings ret; + // AM ret["hbloader"]["applet_heap_size"] = ToBytes(u64{0x0}); ret["hbloader"]["applet_heap_reservation_size"] = ToBytes(u64{0x8600000}); @@ -656,6 +683,24 @@ static Settings GetSettings() { ret["time"]["standard_steady_clock_test_offset_minutes"] = ToBytes(s32{0}); ret["time"]["standard_user_clock_initial_year"] = ToBytes(s32{2023}); + // HID + ret["hid_debug"]["enables_debugpad"] = ToBytes(bool{true}); + ret["hid_debug"]["manages_devices"] = ToBytes(bool{true}); + ret["hid_debug"]["manages_touch_ic_i2c"] = ToBytes(bool{true}); + ret["hid_debug"]["emulate_future_device"] = ToBytes(bool{false}); + ret["hid_debug"]["emulate_mcu_hardware_error"] = ToBytes(bool{false}); + ret["hid_debug"]["enables_rail"] = ToBytes(bool{true}); + ret["hid_debug"]["emulate_firmware_update_failure"] = ToBytes(bool{false}); + ret["hid_debug"]["failure_firmware_update"] = ToBytes(s32{0}); + ret["hid_debug"]["ble_disabled"] = ToBytes(bool{false}); + ret["hid_debug"]["dscale_disabled"] = ToBytes(bool{false}); + ret["hid_debug"]["force_handheld"] = ToBytes(bool{true}); + ret["hid_debug"]["disabled_features_per_id"] = std::vector(0xa8); + ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false}); + + // Settings + ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false}); + return ret; } @@ -708,7 +753,15 @@ void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) { } void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, + "called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, " + "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", + m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode, + m_system_settings.tv_settings.contrast_ratio, + m_system_settings.tv_settings.hdmi_content_type, + m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama, + m_system_settings.tv_settings.tv_resolution, + m_system_settings.tv_settings.tv_underscan); IPC::ResponseBuilder rb{ctx, 10}; rb.Push(ResultSuccess); @@ -735,23 +788,26 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) { } void ISystemSettingsServer::GetDebugModeFlag(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called"); + bool is_debug_mode_enabled = false; + GetSettingsItemValue(is_debug_mode_enabled, "settings_debug", "is_debug_mode_enabled"); + + LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", is_debug_mode_enabled); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(0); + rb.Push(is_debug_mode_enabled); } void ISystemSettingsServer::GetQuestFlag(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(QuestFlag::Retail); + rb.PushEnum(m_system_settings.quest_flag); } void ISystemSettingsServer::GetDeviceTimeZoneLocationName(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called"); + LOG_INFO(Service_SET, "called"); Service::Time::TimeZone::LocationName name{}; auto res = GetDeviceTimeZoneLocationName(name); @@ -762,7 +818,7 @@ void ISystemSettingsServer::GetDeviceTimeZoneLocationName(HLERequestContext& ctx } void ISystemSettingsServer::SetDeviceTimeZoneLocationName(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called"); + LOG_INFO(Service_SET, "called"); IPC::RequestParser rp{ctx}; auto name{rp.PopRaw()}; @@ -775,7 +831,7 @@ void ISystemSettingsServer::SetDeviceTimeZoneLocationName(HLERequestContext& ctx void ISystemSettingsServer::SetRegionCode(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - m_system_settings.region_code = rp.PopEnum(); + m_system_settings.region_code = rp.PopEnum(); SetSaveNeeded(); LOG_INFO(Service_SET, "called, region_code={}", m_system_settings.region_code); @@ -832,15 +888,38 @@ void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(HLERequ } void ISystemSettingsServer::GetPrimaryAlbumStorage(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_INFO(Service_SET, "called, primary_album_storage={}", + m_system_settings.primary_album_storage); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(PrimaryAlbumStorage::SdCard); + rb.PushEnum(m_system_settings.primary_album_storage); +} + +void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.nfc_enable_flag); +} + +void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.nfc_enable_flag = rp.Pop(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); } void ISystemSettingsServer::GetSleepSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}", + m_system_settings.sleep_settings.flags.raw, + m_system_settings.sleep_settings.handheld_sleep_plan, + m_system_settings.sleep_settings.console_sleep_plan); IPC::ResponseBuilder rb{ctx, 5}; rb.Push(ResultSuccess); @@ -861,8 +940,32 @@ void ISystemSettingsServer::SetSleepSettings(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void ISystemSettingsServer::GetWirelessLanEnableFlag(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", + m_system_settings.wireless_lan_enable_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.wireless_lan_enable_flag); +} + +void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.wireless_lan_enable_flag = rp.Pop(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", + m_system_settings.wireless_lan_enable_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); + LOG_INFO(Service_SET, "called, flags={}, timestamp={}", + m_system_settings.initial_launch_settings_packed.flags.raw, + m_system_settings.initial_launch_settings_packed.timestamp.time_point); + IPC::ResponseBuilder rb{ctx, 10}; rb.Push(ResultSuccess); rb.PushRaw(m_system_settings.initial_launch_settings_packed); @@ -913,35 +1016,51 @@ void ISystemSettingsServer::GetProductModel(HLERequestContext& ctx) { rb.Push(product_model); } -void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { - const auto author_id = Common::UUID::MakeDefault(); +void ISystemSettingsServer::GetBluetoothEnableFlag(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", + m_system_settings.bluetooth_enable_flag); - LOG_WARNING(Service_SET, "(STUBBED) called, author_id={}", author_id.FormattedString()); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(m_system_settings.bluetooth_enable_flag); +} + +void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + m_system_settings.bluetooth_enable_flag = rp.Pop(); + SetSaveNeeded(); + + LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", + m_system_settings.bluetooth_enable_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, author_id={}", + m_system_settings.mii_author_id.FormattedString()); IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); - rb.PushRaw(author_id); + rb.PushRaw(m_system_settings.mii_author_id); } void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { - u8 auto_update_flag{}; - - LOG_WARNING(Service_SET, "(STUBBED) called, auto_update_flag={}", auto_update_flag); + LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(auto_update_flag); + rb.Push(m_system_settings.auto_update_enable_flag); } void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { - u8 battery_percentage_flag{1}; - - LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}", - battery_percentage_flag); + LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}", + m_system_settings.battery_percentage_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(battery_percentage_flag); + rb.Push(m_system_settings.battery_percentage_flag); } void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { @@ -968,11 +1087,12 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte } void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_INFO(Service_SET, "called, error_report_share_permission={}", + m_system_settings.error_report_share_permission); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(ErrorReportSharePermission::Denied); + rb.PushEnum(m_system_settings.error_report_share_permission); } void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) { @@ -1014,7 +1134,7 @@ void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { } void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called."); + LOG_INFO(Service_SET, "called"); Service::Time::Clock::SteadyClockTimePoint time_point{}; auto res = GetDeviceTimeZoneLocationUpdatedTime(time_point); @@ -1025,7 +1145,7 @@ void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestConte } void ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called."); + LOG_INFO(Service_SET, "called"); IPC::RequestParser rp{ctx}; auto time_point{rp.PopRaw()}; @@ -1038,7 +1158,7 @@ void ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(HLERequestConte void ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime( HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called."); + LOG_INFO(Service_SET, "called"); Service::Time::Clock::SteadyClockTimePoint time_point{}; auto res = GetUserSystemClockAutomaticCorrectionUpdatedTime(time_point); @@ -1050,7 +1170,7 @@ void ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime( void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "called."); + LOG_INFO(Service_SET, "called"); IPC::RequestParser rp{ctx}; auto time_point{rp.PopRaw()}; @@ -1062,11 +1182,12 @@ void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( } void ISystemSettingsServer::GetChineseTraditionalInputMethod(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_INFO(Service_SET, "called, chinese_traditional_input_method={}", + m_system_settings.chinese_traditional_input_method); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(ChineseTraditionalInputMethod::Unknown0); + rb.PushEnum(m_system_settings.chinese_traditional_input_method); } void ISystemSettingsServer::GetHomeMenuScheme(HLERequestContext& ctx) { @@ -1094,11 +1215,11 @@ void ISystemSettingsServer::GetHomeMenuSchemeModel(HLERequestContext& ctx) { } void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) { - LOG_WARNING(Service_SET, "(STUBBED) called"); + LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(false); + rb.Push(m_system_settings.field_testing_flag); } void ISystemSettingsServer::SetupSettings() { diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h index 6f587e0b3..32716f567 100755 --- a/src/core/hle/service/set/system_settings_server.h +++ b/src/core/hle/service/set/system_settings_server.h @@ -12,10 +12,11 @@ #include "common/uuid.h" #include "core/hle/result.h" #include "core/hle/service/service.h" -#include "core/hle/service/set/appln_settings.h" -#include "core/hle/service/set/device_settings.h" -#include "core/hle/service/set/private_settings.h" -#include "core/hle/service/set/system_settings.h" +#include "core/hle/service/set/setting_formats/appln_settings.h" +#include "core/hle/service/set/setting_formats/device_settings.h" +#include "core/hle/service/set/setting_formats/private_settings.h" +#include "core/hle/service/set/setting_formats/system_settings.h" +#include "core/hle/service/set/settings_types.h" #include "core/hle/service/time/clock_types.h" #include "core/hle/service/time/time_zone_types.h" @@ -24,25 +25,6 @@ class System; } namespace Service::Set { -enum class GetFirmwareVersionType { - Version1, - Version2, -}; - -struct FirmwareVersionFormat { - u8 major; - u8 minor; - u8 micro; - INSERT_PADDING_BYTES(1); - u8 revision_major; - u8 revision_minor; - INSERT_PADDING_BYTES(2); - std::array platform; - std::array version_hash; - std::array display_version; - std::array display_title; -}; -static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size"); Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system, GetFirmwareVersionType type); @@ -55,6 +37,18 @@ public: Result GetSettingsItemValue(std::vector& out_value, const std::string& category, const std::string& name); + template + Result GetSettingsItemValue(T& value, const std::string& category, const std::string& name) { + std::vector data; + const auto result = GetSettingsItemValue(data, category, name); + if (result.IsError()) { + return result; + } + ASSERT(data.size() >= sizeof(T)); + std::memcpy(&value, data.data(), sizeof(T)); + return result; + } + Result GetExternalSteadyClockSourceId(Common::UUID& out_id); Result SetExternalSteadyClockSourceId(Common::UUID id); Result GetUserSystemClockContext(Service::Time::Clock::SystemClockContext& out_context); @@ -80,6 +74,8 @@ private: void SetLanguageCode(HLERequestContext& ctx); void GetFirmwareVersion(HLERequestContext& ctx); void GetFirmwareVersion2(HLERequestContext& ctx); + void GetLockScreenFlag(HLERequestContext& ctx); + void SetLockScreenFlag(HLERequestContext& ctx); void GetExternalSteadyClockSourceId(HLERequestContext& ctx); void SetExternalSteadyClockSourceId(HLERequestContext& ctx); void GetUserSystemClockContext(HLERequestContext& ctx); @@ -108,13 +104,19 @@ private: void IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); void GetPrimaryAlbumStorage(HLERequestContext& ctx); + void GetNfcEnableFlag(HLERequestContext& ctx); + void SetNfcEnableFlag(HLERequestContext& ctx); void GetSleepSettings(HLERequestContext& ctx); void SetSleepSettings(HLERequestContext& ctx); + void GetWirelessLanEnableFlag(HLERequestContext& ctx); + void SetWirelessLanEnableFlag(HLERequestContext& ctx); void GetInitialLaunchSettings(HLERequestContext& ctx); void SetInitialLaunchSettings(HLERequestContext& ctx); void GetDeviceNickName(HLERequestContext& ctx); void SetDeviceNickName(HLERequestContext& ctx); void GetProductModel(HLERequestContext& ctx); + void GetBluetoothEnableFlag(HLERequestContext& ctx); + void SetBluetoothEnableFlag(HLERequestContext& ctx); void GetMiiAuthorId(HLERequestContext& ctx); void GetAutoUpdateEnableFlag(HLERequestContext& ctx); void GetBatteryPercentageFlag(HLERequestContext& ctx); diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 2ab93402d..f2499502d 100755 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -110,6 +110,7 @@ void EmulatedController::ReloadFromSettings() { original_npad_type = npad_type; } + SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Active); Disconnect(); if (player.connected) { Connect(); @@ -144,8 +145,8 @@ void EmulatedController::ReloadColorsFromSettings() { void EmulatedController::LoadDevices() { // TODO(german77): Use more buttons to detect the correct device - const auto left_joycon = button_params[Settings::NativeButton::DRight]; - const auto right_joycon = button_params[Settings::NativeButton::A]; + const auto& left_joycon = button_params[Settings::NativeButton::DRight]; + const auto& right_joycon = button_params[Settings::NativeButton::A]; // Triggers for GC controllers trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; @@ -1208,20 +1209,43 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { controller.nfc_state = controller.nfc_values; } -bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { +bool EmulatedController::SetVibration(bool should_vibrate) { + VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; + if (should_vibrate) { + vibration_value.high_amplitude = 1.0f; + vibration_value.low_amplitude = 1.0f; + } + + return SetVibration(DeviceIndex::Left, vibration_value); +} + +bool EmulatedController::SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command) { + VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; + if (erm_command == Core::HID::VibrationGcErmCommand::Start) { + vibration_value.high_amplitude = 1.0f; + vibration_value.low_amplitude = 1.0f; + } + + return SetVibration(DeviceIndex::Left, vibration_value); +} + +bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationValue& vibration) { if (!is_initialized) { return false; } - if (device_index >= output_devices.size()) { + if (device_index >= DeviceIndex::MaxDeviceIndex) { return false; } - if (!output_devices[device_index]) { + const std::size_t index = static_cast(device_index); + if (!output_devices[index]) { return false; } const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); const auto& player = Settings::values.players.GetValue()[player_index]; const f32 strength = static_cast(player.vibration_strength) / 100.0f; + last_vibration_value = vibration; + if (!player.vibration_enabled) { return false; } @@ -1239,8 +1263,11 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v .high_frequency = vibration.high_frequency, .type = type, }; - return output_devices[device_index]->SetVibration(status) == - Common::Input::DriverResult::Success; + return output_devices[index]->SetVibration(status) == Common::Input::DriverResult::Success; +} + +VibrationValue EmulatedController::GetActualVibrationValue(DeviceIndex device_index) const { + return last_vibration_value; } bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h index 90e536e07..168abe089 100755 --- a/src/hid_core/frontend/emulated_controller.h +++ b/src/hid_core/frontend/emulated_controller.h @@ -355,11 +355,28 @@ public: /// Returns the latest ntag status from the controller const NfcState& GetNfc() const; + /** + * Sends an on/off vibration to the left device + * @return true if vibration had no errors + */ + bool SetVibration(bool should_vibrate); + + /** + * Sends an GC vibration to the left device + * @return true if vibration had no errors + */ + bool SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command); + /** * Sends a specific vibration to the output device * @return true if vibration had no errors */ - bool SetVibration(std::size_t device_index, VibrationValue vibration); + bool SetVibration(DeviceIndex device_index, const VibrationValue& vibration); + + /** + * @return The last sent vibration + */ + VibrationValue GetActualVibrationValue(DeviceIndex device_index) const; /** * Sends a small vibration to the output device @@ -564,6 +581,7 @@ private: f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; u32 turbo_button_state{0}; std::size_t nfc_handles{0}; + VibrationValue last_vibration_value{DEFAULT_VIBRATION_VALUE}; // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index 2c5fe6d51..ca824b4a3 100755 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp @@ -7,6 +7,7 @@ #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/service/ipc_helpers.h" #include "hid_core/hid_core.h" +#include "hid_core/hid_util.h" #include "hid_core/resource_manager.h" #include "hid_core/resources/applet_resource.h" @@ -27,6 +28,10 @@ #include "hid_core/resources/touch_screen/gesture.h" #include "hid_core/resources/touch_screen/touch_screen.h" #include "hid_core/resources/unique_pad/unique_pad.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_base.h" +#include "hid_core/resources/vibration/vibration_device.h" namespace Service::HID { @@ -52,6 +57,7 @@ void ResourceManager::Initialize() { system.HIDCore().ReloadInputDevices(); + handheld_config = std::make_shared(); InitializeHidCommonSampler(); InitializeTouchScreenSampler(); InitializeConsoleSixAxisSampler(); @@ -174,7 +180,7 @@ void ResourceManager::InitializeHidCommonSampler() { debug_pad->SetAppletResource(applet_resource, &shared_mutex); digitizer->SetAppletResource(applet_resource, &shared_mutex); keyboard->SetAppletResource(applet_resource, &shared_mutex); - npad->SetNpadExternals(applet_resource, &shared_mutex); + npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config); six_axis->SetAppletResource(applet_resource, &shared_mutex); mouse->SetAppletResource(applet_resource, &shared_mutex); debug_mouse->SetAppletResource(applet_resource, &shared_mutex); @@ -257,6 +263,121 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { applet_resource->EnableTouchScreen(aruid, is_enabled); } +NpadVibrationBase* ResourceManager::GetVibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + return npad->GetVibrationDevice(handle); +} + +NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + return npad->GetN64VibrationDevice(handle); +} + +NpadVibrationDevice* ResourceManager::GetNSVibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + return npad->GetNSVibrationDevice(handle); +} + +NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + return npad->GetGcVibrationDevice(handle); +} + +Result ResourceManager::SetAruidValidForVibration(u64 aruid, bool is_enabled) { + std::scoped_lock lock{shared_mutex}; + const bool has_changed = applet_resource->SetAruidValidForVibration(aruid, is_enabled); + + if (has_changed) { + auto devices = npad->GetAllVibrationDevices(); + for ([[maybe_unused]] auto* device : devices) { + // TODO + } + } + + auto* vibration_handler = npad->GetVibrationHandler(); + if (aruid != vibration_handler->GetSessionAruid()) { + vibration_handler->EndPermitVibrationSession(); + } + + return ResultSuccess; +} + +void ResourceManager::SetForceHandheldStyleVibration(bool is_forced) { + handheld_config->is_force_handheld_style_vibration = is_forced; +} + +Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) const { + std::scoped_lock lock{shared_mutex}; + is_active = applet_resource->IsVibrationAruidActive(aruid); + return ResultSuccess; +} + +Result ResourceManager::GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, + const Core::HID::VibrationDeviceHandle& handle) { + bool check_device_index = false; + + const Result is_valid = IsVibrationHandleValid(handle); + if (is_valid.IsError()) { + return is_valid; + } + + switch (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: + device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; + check_device_index = true; + break; + case Core::HID::NpadStyleIndex::GameCube: + device_info.type = Core::HID::VibrationDeviceType::GcErm; + break; + case Core::HID::NpadStyleIndex::N64: + device_info.type = Core::HID::VibrationDeviceType::N64; + break; + default: + device_info.type = Core::HID::VibrationDeviceType::Unknown; + break; + } + + device_info.position = Core::HID::VibrationDevicePosition::None; + if (check_device_index) { + switch (handle.device_index) { + case Core::HID::DeviceIndex::Left: + device_info.position = Core::HID::VibrationDevicePosition::Left; + break; + case Core::HID::DeviceIndex::Right: + device_info.position = Core::HID::VibrationDevicePosition::Right; + break; + case Core::HID::DeviceIndex::None: + default: + ASSERT_MSG(false, "DeviceIndex should never be None!"); + break; + } + } + return ResultSuccess; +} + +Result ResourceManager::SendVibrationValue(u64 aruid, + const Core::HID::VibrationDeviceHandle& handle, + const Core::HID::VibrationValue& value) { + bool has_active_aruid{}; + NpadVibrationDevice* device{nullptr}; + Result result = IsVibrationAruidActive(aruid, has_active_aruid); + + if (result.IsSuccess() && has_active_aruid) { + result = IsVibrationHandleValid(handle); + } + if (result.IsSuccess() && has_active_aruid) { + device = GetNSVibrationDevice(handle); + } + if (device != nullptr) { + result = device->SendVibrationValue(value); + } + return result; +} + void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); debug_pad->OnUpdate(core_timing); diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h index 7a21d8eb8..128e00125 100755 --- a/src/hid_core/resource_manager.h +++ b/src/hid_core/resource_manager.h @@ -10,6 +10,12 @@ namespace Core { class System; } +namespace Core::HID { +struct VibrationDeviceHandle; +struct VibrationValue; +struct VibrationDeviceInfo; +} // namespace Core::HID + namespace Core::Timing { struct EventType; } @@ -37,6 +43,11 @@ class SixAxis; class SleepButton; class TouchScreen; class UniquePad; +class NpadVibrationBase; +class NpadN64VibrationDevice; +class NpadGcVibrationDevice; +class NpadVibrationDevice; +struct HandheldConfig; class ResourceManager { @@ -79,6 +90,18 @@ public: void EnablePadInput(u64 aruid, bool is_enabled); void EnableTouchScreen(u64 aruid, bool is_enabled); + NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + Result SetAruidValidForVibration(u64 aruid, bool is_enabled); + void SetForceHandheldStyleVibration(bool is_forced); + Result IsVibrationAruidActive(u64 aruid, bool& is_active) const; + Result GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, + const Core::HID::VibrationDeviceHandle& handle); + Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle, + const Core::HID::VibrationValue& value); + void UpdateControllers(std::chrono::nanoseconds ns_late); void UpdateNpad(std::chrono::nanoseconds ns_late); void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); @@ -113,6 +136,8 @@ private: std::shared_ptr touch_screen = nullptr; std::shared_ptr unique_pad = nullptr; + std::shared_ptr handheld_config = nullptr; + // TODO: Create these resources // std::shared_ptr audio_control = nullptr; // std::shared_ptr button_config = nullptr; diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index d4e4181bf..e399edfd7 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp @@ -115,7 +115,7 @@ Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) if (sensor_state < NpadIrSensorState::Available) { return ResultIrSensorIsNotReady; } - handle = xcd_handle; + // handle = xcd_handle; return ResultSuccess; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h index fe8e005af..997811511 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h @@ -7,6 +7,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Core::HID { +class EmulatedController; +} + namespace Kernel { class KEvent; class KReadableEvent; @@ -50,7 +54,7 @@ private: s32 ref_counter{}; Kernel::KEvent* ir_sensor_event{nullptr}; - u64 xcd_handle{}; + Core::HID::EmulatedController* xcd_handle{}; NpadIrSensorState sensor_state{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index 2c7691d7c..435b095f0 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "hid_core/hid_core.h" #include "hid_core/hid_result.h" #include "hid_core/resources/abstracted_pad/abstract_pad.h" #include "hid_core/resources/applet_resource.h" @@ -16,7 +17,7 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, CaptureButtonResource* capture_button_resource, HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, - VibrationHandler* vibration) { + NpadVibration* vibration, Core::HID::HIDCore* core) { applet_resource_holder = applet_resource; properties_handler.SetAppletResource(applet_resource_holder); @@ -35,13 +36,14 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); mcu_handler.SetPropertiesHandler(&properties_handler); - std::array vibration_devices{&vibration_left, &vibration_right}; vibration_handler.SetAppletResource(applet_resource_holder); vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); vibration_handler.SetPropertiesHandler(&properties_handler); vibration_handler.SetN64Vibration(&vibration_n64); - vibration_handler.SetVibration(vibration_devices); + vibration_handler.SetVibration(&vibration_left, &vibration_right); vibration_handler.SetGcVibration(&vibration_gc); + vibration_handler.SetVibrationHandler(vibration); + vibration_handler.SetHidCore(core); sixaxis_handler.SetAppletResource(applet_resource_holder); sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); @@ -239,11 +241,6 @@ NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex devi return &vibration_left; } -void AbstractPad::GetLeftRightVibrationDevice(std::vector list) { - list.emplace_back(&vibration_left); - list.emplace_back(&vibration_right); -} - NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { return &vibration_gc; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h index cbdf84af7..329792457 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.h +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h @@ -32,7 +32,6 @@ class AppletResource; class SixAxisResource; class PalmaResource; class NPadResource; -class AbstractPad; class NpadLastActiveHandler; class NpadIrNfcHandler; class UniquePads; @@ -44,7 +43,6 @@ class NpadGcVibration; class CaptureButtonResource; class HomeButtonResource; -class VibrationHandler; struct HandheldConfig; @@ -57,7 +55,8 @@ public: void SetExternals(AppletResourceHolder* applet_resource, CaptureButtonResource* capture_button_resource, HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, - PalmaResource* palma_resource, VibrationHandler* vibration); + PalmaResource* palma_resource, NpadVibration* vibration, + Core::HID::HIDCore* core); void SetNpadId(Core::HID::NpadIdType npad_id); Result Activate(); @@ -78,7 +77,6 @@ public: NpadN64VibrationDevice* GetN64VibrationDevice(); NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); - void GetLeftRightVibrationDevice(std::vector list); NpadGcVibrationDevice* GetGCVibrationDevice(); Core::HID::NpadIdType GetLastActiveNpad(); diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index a00d6c9de..ca64b0a43 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" #include "hid_core/hid_result.h" #include "hid_core/hid_util.h" #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" @@ -30,14 +32,22 @@ void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHa properties_handler = handler; } +void NpadAbstractVibrationHandler::SetVibrationHandler(NpadVibration* handler) { + vibration_handler = handler; +} + +void NpadAbstractVibrationHandler::SetHidCore(Core::HID::HIDCore* core) { + hid_core = core; +} + void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { n64_vibration_device = n64_device; } -void NpadAbstractVibrationHandler::SetVibration(std::span device) { - for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { - vibration_device[i] = device[i]; - } +void NpadAbstractVibrationHandler::SetVibration(NpadVibrationDevice* left_device, + NpadVibrationDevice* right_device) { + left_vibration_device = left_device; + right_vibration_device = right_device; } void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { @@ -69,5 +79,29 @@ void NpadAbstractVibrationHandler::UpdateVibrationState() { if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { // TODO } + + // TODO: This function isn't accurate. It's supposed to get 5 abstracted pads from the + // NpadAbstractPropertiesHandler but this handler isn't fully implemented yet + IAbstractedPad abstracted_pad{}; + const auto npad_id = properties_handler->GetNpadId(); + abstracted_pad.xcd_handle = hid_core->GetEmulatedController(npad_id); + abstracted_pad.internal_flags.is_connected.Assign(abstracted_pad.xcd_handle->IsConnected()); + + if (abstracted_pad.internal_flags.is_connected) { + left_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Left, + vibration_handler); + right_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Right, + vibration_handler); + gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); + gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); + n64_vibration_device->Mount(abstracted_pad, vibration_handler); + return; + } + + left_vibration_device->Unmount(); + right_vibration_device->Unmount(); + gc_vibration_device->Unmount(); + gc_vibration_device->Unmount(); + n64_vibration_device->Unmount(); } } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h index aeb07ce86..8bc8129c2 100755 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h @@ -9,6 +9,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Core::HID { +class HIDCore; +} + namespace Service::HID { struct AppletResourceHolder; class NpadAbstractedPadHolder; @@ -27,9 +31,11 @@ public: void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); void SetAppletResource(AppletResourceHolder* applet_resource); void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); + void SetVibrationHandler(NpadVibration* handler); + void SetHidCore(Core::HID::HIDCore* core); void SetN64Vibration(NpadN64VibrationDevice* n64_device); - void SetVibration(std::span device); + void SetVibration(NpadVibrationDevice* left_device, NpadVibrationDevice* right_device); void SetGcVibration(NpadGcVibrationDevice* gc_device); Result IncrementRefCounter(); @@ -41,9 +47,11 @@ private: AppletResourceHolder* applet_resource_holder{nullptr}; NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; NpadAbstractPropertiesHandler* properties_handler{nullptr}; + Core::HID::HIDCore* hid_core{nullptr}; NpadN64VibrationDevice* n64_vibration_device{nullptr}; - std::array vibration_device{}; + NpadVibrationDevice* left_vibration_device{}; + NpadVibrationDevice* right_vibration_device{}; NpadGcVibrationDevice* gc_vibration_device{nullptr}; NpadVibration* vibration_handler{nullptr}; s32 ref_counter{}; diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index a84826050..db4134037 100755 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp @@ -200,6 +200,25 @@ void AppletResource::EnableInput(u64 aruid, bool is_enabled) { data[index].flag.enable_touchscreen.Assign(is_enabled); } +bool AppletResource::SetAruidValidForVibration(u64 aruid, bool is_enabled) { + const u64 index = GetIndexFromAruid(aruid); + if (index >= AruidIndexMax) { + return false; + } + + if (!is_enabled && aruid == active_vibration_aruid) { + active_vibration_aruid = SystemAruid; + return true; + } + + if (is_enabled && aruid != active_vibration_aruid) { + active_vibration_aruid = aruid; + return true; + } + + return false; +} + void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { const u64 index = GetIndexFromAruid(aruid); if (index >= AruidIndexMax) { diff --git a/src/hid_core/resources/applet_resource.h b/src/hid_core/resources/applet_resource.h index f3f32bac1..e9710d306 100755 --- a/src/hid_core/resources/applet_resource.h +++ b/src/hid_core/resources/applet_resource.h @@ -101,6 +101,7 @@ public: Result DestroySevenSixAxisTransferMemory(); void EnableInput(u64 aruid, bool is_enabled); + bool SetAruidValidForVibration(u64 aruid, bool is_enabled); void EnableSixAxisSensor(u64 aruid, bool is_enabled); void EnablePadInput(u64 aruid, bool is_enabled); void EnableTouchScreen(u64 aruid, bool is_enabled); diff --git a/src/hid_core/resources/hid_firmware_settings.cpp b/src/hid_core/resources/hid_firmware_settings.cpp index 9fa0db17e..00ceff7e6 100755 --- a/src/hid_core/resources/hid_firmware_settings.cpp +++ b/src/hid_core/resources/hid_firmware_settings.cpp @@ -1,11 +1,14 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" #include "hid_core/resources/hid_firmware_settings.h" namespace Service::HID { -HidFirmwareSettings::HidFirmwareSettings() { +HidFirmwareSettings::HidFirmwareSettings(Core::System& system) { + m_set_sys = system.ServiceManager().GetService("set:sys"); LoadSettings(true); } @@ -18,21 +21,25 @@ void HidFirmwareSettings::LoadSettings(bool reload_config) { return; } - // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values - - is_debug_pad_enabled = true; - is_device_managed = true; - is_touch_i2c_managed = is_device_managed; - is_future_devices_emulated = false; - is_mcu_hardware_error_emulated = false; - is_rail_enabled = true; - is_firmware_update_failure_emulated = false; + m_set_sys->GetSettingsItemValue(is_debug_pad_enabled, "hid_debug", "enables_debugpad"); + m_set_sys->GetSettingsItemValue(is_device_managed, "hid_debug", "manages_devices"); + m_set_sys->GetSettingsItemValue(is_touch_i2c_managed, "hid_debug", + "manages_touch_ic_i2c"); + m_set_sys->GetSettingsItemValue(is_future_devices_emulated, "hid_debug", + "emulate_future_device"); + m_set_sys->GetSettingsItemValue(is_mcu_hardware_error_emulated, "hid_debug", + "emulate_mcu_hardware_error"); + m_set_sys->GetSettingsItemValue(is_rail_enabled, "hid_debug", "enables_rail"); + m_set_sys->GetSettingsItemValue(is_firmware_update_failure_emulated, "hid_debug", + "emulate_firmware_update_failure"); is_firmware_update_failure = {}; - is_ble_disabled = false; - is_dscale_disabled = false; - is_handheld_forced = true; + m_set_sys->GetSettingsItemValue(is_ble_disabled, "hid_debug", "ble_disabled"); + m_set_sys->GetSettingsItemValue(is_dscale_disabled, "hid_debug", "dscale_disabled"); + m_set_sys->GetSettingsItemValue(is_handheld_forced, "hid_debug", "force_handheld"); features_per_id_disabled = {}; - is_touch_firmware_auto_update_disabled = false; + m_set_sys->GetSettingsItemValue(is_touch_firmware_auto_update_disabled, "hid_debug", + "touch_firmware_auto_update_disabled"); + is_initialized = true; } diff --git a/src/hid_core/resources/hid_firmware_settings.h b/src/hid_core/resources/hid_firmware_settings.h index 00201fd94..3694fa9a3 100755 --- a/src/hid_core/resources/hid_firmware_settings.h +++ b/src/hid_core/resources/hid_firmware_settings.h @@ -5,6 +5,14 @@ #include "common/common_types.h" +namespace Core { +class System; +} + +namespace Service::Set { +class ISystemSettingsServer; +} + namespace Service::HID { /// Loads firmware config from nn::settings::fwdbg @@ -13,7 +21,7 @@ public: using FirmwareSetting = std::array; using FeaturesPerId = std::array; - HidFirmwareSettings(); + HidFirmwareSettings(Core::System& system); void Reload(); void LoadSettings(bool reload_config); @@ -49,6 +57,8 @@ private: bool is_touch_firmware_auto_update_disabled{}; FirmwareSetting is_firmware_update_failure{}; FeaturesPerId features_per_id_disabled{}; + + std::shared_ptr m_set_sys; }; } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 97537a2e2..310fa8ba7 100755 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -21,6 +21,7 @@ #include "hid_core/hid_util.h" #include "hid_core/resources/applet_resource.h" #include "hid_core/resources/npad/npad.h" +#include "hid_core/resources/npad/npad_vibration.h" #include "hid_core/resources/shared_memory_format.h" namespace Service::HID { @@ -31,10 +32,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { auto& controller = controller_data[aruid_index][i]; controller.device = hid_core.GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] - .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; Core::HID::ControllerUpdateCallback engine_callback{ .on_change = [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, @@ -43,6 +40,10 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service controller.callback_key = controller.device->SetCallback(engine_callback); } } + for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { + abstracted_pads[i] = AbstractPad{}; + abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); + } } NPad::~NPad() { @@ -359,6 +360,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); WriteEmptyEntry(controller.shared_memory); hid_core.SetLastActiveController(npad_id); + abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); } void NPad::WriteEmptyEntry(NpadInternalState* npad) { @@ -740,171 +742,6 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: return true; } -bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index, - const Core::HID::VibrationValue& vibration_value) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!controller.device->IsConnected()) { - return false; - } - - if (!controller.device->IsVibrationEnabled(device_index)) { - if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || - controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { - // Send an empty vibration to stop any vibrations. - Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; - controller.device->SetVibration(device_index, vibration); - // Then reset the vibration value to its default value. - controller.vibration[device_index].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - } - - return false; - } - - if (!Settings::values.enable_accurate_vibrations.GetValue()) { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::steady_clock; - - const auto now = steady_clock::now(); - - // Filter out non-zero vibrations that are within 15ms of each other. - if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && - duration_cast( - now - controller.vibration[device_index].last_vibration_timepoint) < - milliseconds(15)) { - return false; - } - - controller.vibration[device_index].last_vibration_timepoint = now; - } - - Core::HID::VibrationValue vibration{ - vibration_value.low_amplitude, vibration_value.low_frequency, - vibration_value.high_amplitude, vibration_value.high_frequency}; - return controller.device->SetVibration(device_index, vibration); -} - -void NPad::VibrateController(u64 aruid, - const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - - if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { - return; - } - - if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { - ASSERT_MSG(false, "DeviceIndex should never be None!"); - return; - } - - // Some games try to send mismatched parameters in the device handle, block these. - if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || - (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { - return; - } - - // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.low_amplitude == - controller.vibration[device_index].latest_vibration_value.low_amplitude && - vibration_value.high_amplitude == - controller.vibration[device_index].latest_vibration_value.high_amplitude) { - return; - } - - if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, - vibration_value)) { - controller.vibration[device_index].latest_vibration_value = vibration_value; - } -} - -void NPad::VibrateControllers( - u64 aruid, std::span vibration_device_handles, - std::span vibration_values) { - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - ASSERT_OR_EXECUTE_MSG( - vibration_device_handles.size() == vibration_values.size(), { return; }, - "The amount of device handles does not match with the amount of vibration values," - "this is undefined behavior!"); - - for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { - VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); - } -} - -Core::HID::VibrationValue NPad::GetLastVibration( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return {}; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].latest_vibration_value; -} - -void NPad::InitializeVibrationDevice( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); - const auto npad_index = static_cast(vibration_device_handle.npad_id); - const auto device_index = static_cast(vibration_device_handle.device_index); - - if (aruid == 0) { - return; - } - - InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); -} - -void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!Settings::values.vibration_enabled.GetValue()) { - controller.vibration[device_index].device_mounted = false; - return; - } - - controller.vibration[device_index].device_mounted = - controller.device->IsVibrationEnabled(device_index); -} - -void NPad::SetPermitVibrationSession(bool permit_vibration_session) { - permit_vibration_session_enabled = permit_vibration_session; -} - -bool NPad::IsVibrationDeviceMounted( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return false; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast(vibration_device_handle.device_index); - return controller.vibration[device_index].device_mounted; -} - Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { std::scoped_lock lock{mutex}; @@ -936,11 +773,6 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); - controller.vibration[device_idx].device_mounted = false; - } auto* shared_memory = controller.shared_memory; // Don't reset shared_memory->assignment_mode this value is persistent @@ -1236,22 +1068,17 @@ void NPad::UnregisterAppletResourceUserId(u64 aruid) { } void NPad::SetNpadExternals(std::shared_ptr resource, - std::recursive_mutex* shared_mutex) { + std::recursive_mutex* shared_mutex, + std::shared_ptr handheld_config) { applet_resource_holder.applet_resource = resource; applet_resource_holder.shared_mutex = shared_mutex; applet_resource_holder.shared_npad_resource = &npad_resource; -} + applet_resource_holder.handheld_config = handheld_config; -NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { - const auto npad_id = static_cast(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); + for (auto& abstract_pad : abstracted_pads) { + abstract_pad.SetExternals(&applet_resource_holder, nullptr, nullptr, nullptr, nullptr, + &vibration_handler, &hid_core); + } } NPad::NpadControllerData& NPad::GetControllerFromHandle( @@ -1389,4 +1216,97 @@ Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const { return ResultSuccess; } +NpadVibration* NPad::GetVibrationHandler() { + return &vibration_handler; +} + +std::vector NPad::GetAllVibrationDevices() { + std::vector vibration_devices; + + for (auto& abstract_pad : abstracted_pads) { + auto* left_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Left); + auto* right_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Right); + auto* n64_device = abstract_pad.GetGCVibrationDevice(); + auto* gc_device = abstract_pad.GetGCVibrationDevice(); + + if (left_device != nullptr) { + vibration_devices.emplace_back(left_device); + } + if (right_device != nullptr) { + vibration_devices.emplace_back(right_device); + } + if (n64_device != nullptr) { + vibration_devices.emplace_back(n64_device); + } + if (gc_device != nullptr) { + vibration_devices.emplace_back(gc_device); + } + } + + return vibration_devices; +} + +NpadVibrationBase* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde == Core::HID::NpadStyleIndex::GameCube) { + return abstracted_pads[npad_index].GetGCVibrationDevice(); + } + if (style_inde == Core::HID::NpadStyleIndex::N64) { + return abstracted_pads[npad_index].GetN64VibrationDevice(); + } + return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); +} + +NpadN64VibrationDevice* NPad::GetN64VibrationDevice( + const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde != Core::HID::NpadStyleIndex::N64) { + return nullptr; + } + return abstracted_pads[npad_index].GetN64VibrationDevice(); +} + +NpadVibrationDevice* NPad::GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde == Core::HID::NpadStyleIndex::GameCube || + style_inde == Core::HID::NpadStyleIndex::N64) { + return nullptr; + } + + return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); +} + +NpadGcVibrationDevice* NPad::GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { + if (IsVibrationHandleValid(handle).IsError()) { + return nullptr; + } + + const auto npad_index = NpadIdTypeToIndex(static_cast(handle.npad_id)); + const auto style_inde = static_cast(handle.npad_type); + if (style_inde != Core::HID::NpadStyleIndex::GameCube) { + return nullptr; + } + return abstracted_pads[npad_index].GetGCVibrationDevice(); +} + +void NPad::UpdateHandheldAbstractState() { + std::scoped_lock lock{mutex}; + abstracted_pads[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); +} + } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 01f3dabb1..18b25c688 100755 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h @@ -10,9 +10,15 @@ #include "common/common_types.h" #include "hid_core/hid_types.h" +#include "hid_core/resources/abstracted_pad/abstract_pad.h" #include "hid_core/resources/controller_base.h" #include "hid_core/resources/npad/npad_resource.h" #include "hid_core/resources/npad/npad_types.h" +#include "hid_core/resources/npad/npad_vibration.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_base.h" +#include "hid_core/resources/vibration/vibration_device.h" namespace Core::HID { class EmulatedController; @@ -32,6 +38,7 @@ union Result; namespace Service::HID { class AppletResource; +struct HandheldConfig; struct NpadInternalState; struct NpadSixAxisSensorLifo; struct NpadSharedMemoryFormat; @@ -68,31 +75,6 @@ public: bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); - bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index, - const Core::HID::VibrationValue& vibration_value); - - void VibrateController(u64 aruid, - const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value); - - void VibrateControllers( - u64 aruid, std::span vibration_device_handles, - std::span vibration_values); - - Core::HID::VibrationValue GetLastVibration( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - - void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); - - void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index); - - void SetPermitVibrationSession(bool permit_vibration_session); - - bool IsVibrationDeviceMounted( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id); @@ -145,7 +127,8 @@ public: Result RegisterAppletResourceUserId(u64 aruid); void UnregisterAppletResourceUserId(u64 aruid); void SetNpadExternals(std::shared_ptr resource, - std::recursive_mutex* shared_mutex); + std::recursive_mutex* shared_mutex, + std::shared_ptr handheld_config); AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); @@ -161,18 +144,20 @@ public: Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; -private: - struct VibrationData { - bool device_mounted{}; - Core::HID::VibrationValue latest_vibration_value{}; - std::chrono::steady_clock::time_point last_vibration_timepoint{}; - }; + NpadVibration* GetVibrationHandler(); + std::vector GetAllVibrationDevices(); + NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); + void UpdateHandheldAbstractState(); + +private: struct NpadControllerData { NpadInternalState* shared_memory = nullptr; Core::HID::EmulatedController* device = nullptr; - std::array vibration{}; bool is_connected{}; // Dual joycons can have only one side connected @@ -191,10 +176,6 @@ private: void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); void WriteEmptyEntry(NpadInternalState* npad); - NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; NpadControllerData& GetControllerFromHandle( u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); const NpadControllerData& GetControllerFromHandle( @@ -215,11 +196,13 @@ private: mutable std::mutex mutex; NPadResource npad_resource; AppletResourceHolder applet_resource_holder{}; + std::array abstracted_pads; + NpadVibration vibration_handler{}; + Kernel::KEvent* input_event{nullptr}; std::mutex* input_mutex{nullptr}; std::atomic press_state{}; - bool permit_vibration_session_enabled; std::array, AruidIndexMax> controller_data{}; }; diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h index fd86c8e40..92700d69a 100755 --- a/src/hid_core/resources/npad/npad_types.h +++ b/src/hid_core/resources/npad/npad_types.h @@ -8,6 +8,10 @@ #include "common/common_types.h" #include "hid_core/hid_types.h" +namespace Core::HID { +class EmulatedController; +} + namespace Service::HID { static constexpr std::size_t MaxSupportedNpadIdTypes = 10; static constexpr std::size_t StyleIndexCount = 7; @@ -348,7 +352,7 @@ struct IAbstractedPad { u8 indicator; std::vector virtual_six_axis_sensor_acceleration; std::vector virtual_six_axis_sensor_angle; - u64 xcd_handle; + Core::HID::EmulatedController* xcd_handle; u64 color; }; } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp index 7056e8eab..05aad4c54 100755 --- a/src/hid_core/resources/npad/npad_vibration.cpp +++ b/src/hid_core/resources/npad/npad_vibration.cpp @@ -77,4 +77,8 @@ Result NpadVibration::EndPermitVibrationSession() { return ResultSuccess; } +u64 NpadVibration::GetSessionAruid() const { + return session_aruid; +} + } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h index 0748aeffc..d5a95f2a0 100755 --- a/src/hid_core/resources/npad/npad_vibration.h +++ b/src/hid_core/resources/npad/npad_vibration.h @@ -25,6 +25,8 @@ public: Result BeginPermitVibrationSession(u64 aruid); Result EndPermitVibrationSession(); + u64 GetSessionAruid() const; + private: f32 volume{}; u64 session_aruid{}; diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp index f01f81b9a..ad42b9d66 100755 --- a/src/hid_core/resources/vibration/gc_vibration_device.cpp +++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_result.h" #include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/npad/npad_vibration.h" @@ -10,24 +11,25 @@ namespace Service::HID { NpadGcVibrationDevice::NpadGcVibrationDevice() {} -Result NpadGcVibrationDevice::IncrementRefCounter() { +Result NpadGcVibrationDevice::Activate() { if (ref_counter == 0 && is_mounted) { f32 volume = 1.0f; const auto result = vibration_handler->GetVibrationVolume(volume); if (result.IsSuccess()) { - // TODO: SendVibrationGcErmCommand + xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); } } + ref_counter++; return ResultSuccess; } -Result NpadGcVibrationDevice::DecrementRefCounter() { - if (ref_counter == 1 && !is_mounted) { +Result NpadGcVibrationDevice::Deactivate() { + if (ref_counter == 1 && is_mounted) { f32 volume = 1.0f; const auto result = vibration_handler->GetVibrationVolume(volume); if (result.IsSuccess()) { - // TODO: SendVibrationGcErmCommand + xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); } } @@ -38,6 +40,48 @@ Result NpadGcVibrationDevice::DecrementRefCounter() { return ResultSuccess; } +Result NpadGcVibrationDevice::Mount(IAbstractedPad& abstracted_pad, u32 slot, + NpadVibration* handler) { + if (!abstracted_pad.internal_flags.is_connected) { + return ResultSuccess; + } + + // TODO: This device doesn't use a xcd handle instead has an GC adapter handle. This is just to + // keep compatibility with the front end. + xcd_handle = abstracted_pad.xcd_handle; + adapter_slot = slot; + vibration_handler = handler; + is_mounted = true; + + if (ref_counter == 0) { + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); + } + + return ResultSuccess; +} + +Result NpadGcVibrationDevice::Unmount() { + if (ref_counter == 0 || !is_mounted) { + is_mounted = false; + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); + } + + is_mounted = false; + return ResultSuccess; +} + Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { if (!is_mounted) { return ResultSuccess; @@ -55,7 +99,7 @@ Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcEr return ResultSuccess; } } - // TODO: SendVibrationGcErmCommand + xcd_handle->SetVibration(adapter_slot, command); return ResultSuccess; } diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h index 87abca57d..c624cbb28 100755 --- a/src/hid_core/resources/vibration/gc_vibration_device.h +++ b/src/hid_core/resources/vibration/gc_vibration_device.h @@ -20,12 +20,18 @@ class NpadGcVibrationDevice final : public NpadVibrationBase { public: explicit NpadGcVibrationDevice(); - Result IncrementRefCounter() override; - Result DecrementRefCounter() override; + Result Activate() override; + Result Deactivate() override; + + Result Mount(IAbstractedPad& abstracted_pad, u32 slot, NpadVibration* handler); + Result Unmount(); Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); + +private: + u32 adapter_slot; }; } // namespace Service::HID diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp index 639f87abf..94ad37c8f 100755 --- a/src/hid_core/resources/vibration/n64_vibration_device.cpp +++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_result.h" #include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/npad/npad_vibration.h" @@ -10,12 +11,12 @@ namespace Service::HID { NpadN64VibrationDevice::NpadN64VibrationDevice() {} -Result NpadN64VibrationDevice::IncrementRefCounter() { +Result NpadN64VibrationDevice::Activate() { if (ref_counter == 0 && is_mounted) { f32 volume = 1.0f; const auto result = vibration_handler->GetVibrationVolume(volume); if (result.IsSuccess()) { - // TODO: SendVibrationInBool + xcd_handle->SetVibration(false); } } @@ -23,19 +24,12 @@ Result NpadN64VibrationDevice::IncrementRefCounter() { return ResultSuccess; } -Result NpadN64VibrationDevice::DecrementRefCounter() { - if (ref_counter == 1) { - if (!is_mounted) { - ref_counter = 0; - if (is_mounted != false) { - // TODO: SendVibrationInBool - } - return ResultSuccess; - } +Result NpadN64VibrationDevice::Deactivate() { + if (ref_counter == 1 && is_mounted) { f32 volume = 1.0f; const auto result = vibration_handler->GetVibrationVolume(volume); if (result.IsSuccess()) { - // TODO + xcd_handle->SetVibration(false); } } @@ -46,6 +40,43 @@ Result NpadN64VibrationDevice::DecrementRefCounter() { return ResultSuccess; } +Result NpadN64VibrationDevice::Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler) { + if (!abstracted_pad.internal_flags.is_connected) { + return ResultSuccess; + } + xcd_handle = abstracted_pad.xcd_handle; + vibration_handler = handler; + is_mounted = true; + + if (ref_counter == 0) { + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(false); + } + + return ResultSuccess; +} + +Result NpadN64VibrationDevice::Unmount() { + if (ref_counter == 0 || !is_mounted) { + is_mounted = false; + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(false); + } + + is_mounted = false; + return ResultSuccess; +} + Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { if (ref_counter < 1) { return ResultVibrationNotInitialized; @@ -56,7 +87,7 @@ Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { if (result.IsError()) { return result; } - // TODO: SendVibrationInBool + xcd_handle->SetVibration(false); } return ResultSuccess; } diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h index 54e6efc1a..09de7701c 100755 --- a/src/hid_core/resources/vibration/n64_vibration_device.h +++ b/src/hid_core/resources/vibration/n64_vibration_device.h @@ -14,14 +14,18 @@ namespace Service::HID { class NpadVibration; +struct IAbstractedPad; /// Handles Npad request from HID interfaces class NpadN64VibrationDevice final : public NpadVibrationBase { public: explicit NpadN64VibrationDevice(); - Result IncrementRefCounter() override; - Result DecrementRefCounter() override; + Result Activate() override; + Result Deactivate() override; + + Result Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler); + Result Unmount(); Result SendValueInBool(bool is_vibrating); Result SendVibrationNotificationPattern(u32 pattern); diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp index 350f349c2..f28d30406 100755 --- a/src/hid_core/resources/vibration/vibration_base.cpp +++ b/src/hid_core/resources/vibration/vibration_base.cpp @@ -10,12 +10,12 @@ namespace Service::HID { NpadVibrationBase::NpadVibrationBase() {} -Result NpadVibrationBase::IncrementRefCounter() { +Result NpadVibrationBase::Activate() { ref_counter++; return ResultSuccess; } -Result NpadVibrationBase::DecrementRefCounter() { +Result NpadVibrationBase::Deactivate() { if (ref_counter > 0) { ref_counter--; } diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h index c6c5fc4d9..69c26e669 100755 --- a/src/hid_core/resources/vibration/vibration_base.h +++ b/src/hid_core/resources/vibration/vibration_base.h @@ -6,6 +6,10 @@ #include "common/common_types.h" #include "core/hle/result.h" +namespace Core::HID { +class EmulatedController; +} + namespace Service::HID { class NpadVibration; @@ -14,13 +18,13 @@ class NpadVibrationBase { public: explicit NpadVibrationBase(); - virtual Result IncrementRefCounter(); - virtual Result DecrementRefCounter(); + virtual Result Activate(); + virtual Result Deactivate(); bool IsVibrationMounted() const; protected: - u64 xcd_handle{}; + Core::HID::EmulatedController* xcd_handle{nullptr}; s32 ref_counter{}; bool is_mounted{}; NpadVibration* vibration_handler{nullptr}; diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp index 888c3a7ed..08b14591f 100755 --- a/src/hid_core/resources/vibration/vibration_device.cpp +++ b/src/hid_core/resources/vibration/vibration_device.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_result.h" #include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/npad/npad_vibration.h" @@ -10,12 +11,30 @@ namespace Service::HID { NpadVibrationDevice::NpadVibrationDevice() {} -Result NpadVibrationDevice::IncrementRefCounter() { +Result NpadVibrationDevice::Activate() { + if (ref_counter == 0 && is_mounted) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); + // TODO: SendNotificationPattern; + } + } + ref_counter++; return ResultSuccess; } -Result NpadVibrationDevice::DecrementRefCounter() { +Result NpadVibrationDevice::Deactivate() { + if (ref_counter == 1 && is_mounted) { + f32 volume = 1.0f; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); + // TODO: SendNotificationPattern; + } + } + if (ref_counter > 0) { ref_counter--; } @@ -23,6 +42,45 @@ Result NpadVibrationDevice::DecrementRefCounter() { return ResultSuccess; } +Result NpadVibrationDevice::Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, + NpadVibration* handler) { + if (!abstracted_pad.internal_flags.is_connected) { + return ResultSuccess; + } + xcd_handle = abstracted_pad.xcd_handle; + device_index = index; + vibration_handler = handler; + is_mounted = true; + + if (ref_counter == 0) { + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(false); + } + + return ResultSuccess; +} + +Result NpadVibrationDevice::Unmount() { + if (ref_counter == 0 || !is_mounted) { + is_mounted = false; + return ResultSuccess; + } + + f32 volume{1.0f}; + const auto result = vibration_handler->GetVibrationVolume(volume); + if (result.IsSuccess()) { + xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); + } + + is_mounted = false; + return ResultSuccess; +} + Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { if (ref_counter == 0) { return ResultVibrationNotInitialized; @@ -37,7 +95,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& return result; } if (volume <= 0.0f) { - // TODO: SendVibrationValue + xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); return ResultSuccess; } @@ -45,7 +103,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& vibration_value.high_amplitude *= volume; vibration_value.low_amplitude *= volume; - // TODO: SendVibrationValue + xcd_handle->SetVibration(device_index, vibration_value); return ResultSuccess; } @@ -63,11 +121,11 @@ Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u3 pattern = 0; } - // return xcd_handle->SendVibrationNotificationPattern(pattern); + // TODO: SendVibrationNotificationPattern; return ResultSuccess; } -Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) { +Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) const { if (ref_counter < 1) { return ResultVibrationNotInitialized; } @@ -77,7 +135,7 @@ Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& o return ResultSuccess; } - // TODO: SendVibrationValue + out_value = xcd_handle->GetActualVibrationValue(device_index); return ResultSuccess; } diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h index 3574ad60b..c2f9891d3 100755 --- a/src/hid_core/resources/vibration/vibration_device.h +++ b/src/hid_core/resources/vibration/vibration_device.h @@ -12,6 +12,10 @@ #include "hid_core/resources/npad/npad_types.h" #include "hid_core/resources/vibration/vibration_base.h" +namespace Core::HID { +enum class DeviceIndex : u8; +} + namespace Service::HID { class NpadVibration; @@ -20,16 +24,20 @@ class NpadVibrationDevice final : public NpadVibrationBase { public: explicit NpadVibrationDevice(); - Result IncrementRefCounter(); - Result DecrementRefCounter(); + Result Activate(); + Result Deactivate(); + + Result Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, + NpadVibration* handler); + Result Unmount(); Result SendVibrationValue(const Core::HID::VibrationValue& value); Result SendVibrationNotificationPattern(u32 pattern); - Result GetActualVibrationValue(Core::HID::VibrationValue& out_value); + Result GetActualVibrationValue(Core::HID::VibrationValue& out_value) const; private: - u32 device_index{}; + Core::HID::DeviceIndex device_index{}; }; } // namespace Service::HID diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index b75052a5c..8d07d1b1a 100755 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -116,8 +116,8 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type .high_amplitude = 1.0f, .high_frequency = 320.0f, }; - controller->SetVibration(0, vibration); - controller->SetVibration(1, vibration); + controller->SetVibration(Core::HID::DeviceIndex::Left, vibration); + controller->SetVibration(Core::HID::DeviceIndex::Right, vibration); // Restore previous values player.vibration_enabled = old_vibration_enabled; @@ -127,7 +127,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type void ConfigureVibration::StopVibrations() { for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { auto controller = hid_core.GetEmulatedControllerByIndex(i); - controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); - controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); + controller->SetVibration(Core::HID::DeviceIndex::Left, Core::HID::DEFAULT_VIBRATION_VALUE); + controller->SetVibration(Core::HID::DeviceIndex::Right, Core::HID::DEFAULT_VIBRATION_VALUE); } }