From cb004d1ba1bde740ba10418ac3f3cfd2db8ffac7 Mon Sep 17 00:00:00 2001 From: FrozenAra Date: Wed, 1 Nov 2023 01:09:33 +0100 Subject: [PATCH] Implemented qlaunch version of the controller applet --- src/core/hid/hid_types.h | 7 + src/core/hle/service/am/am.cpp | 91 +++++- src/core/hle/service/am/am.h | 3 + .../service/am/applets/applet_controller.h | 2 +- src/core/hle/service/btm/btm.cpp | 56 +++- src/core/hle/service/hid/controllers/npad.cpp | 16 + src/core/hle/service/hid/controllers/npad.h | 72 +++-- src/core/hle/service/hid/hid_server.cpp | 4 +- .../hle/service/hid/hid_system_server.cpp | 293 ++++++++++++++++-- src/core/hle/service/hid/hid_system_server.h | 23 ++ src/core/hle/service/ldn/ldn.cpp | 10 +- src/core/hle/service/set/set_sys.cpp | 30 +- src/core/hle/service/set/set_sys.h | 12 + src/yuzu/main.cpp | 41 ++- src/yuzu/main.h | 1 + src/yuzu/main.ui | 22 +- 16 files changed, 594 insertions(+), 89 deletions(-) diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 9d48cd90e..70fcc6b69 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -218,6 +218,13 @@ enum class NpadIdType : u32 { Invalid = 0xFFFFFFFF, }; +enum class NpadInterfaceType : u8 { + Bluetooth = 1, + Rail = 2, + Usb = 3, + Embedded = 4, +}; + // This is nn::hid::NpadStyleIndex enum class NpadStyleIndex : u8 { None = 0, diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index cc643ea09..a266d7c21 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -13,6 +13,7 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/savedata_factory.h" +#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/result.h" @@ -21,6 +22,7 @@ #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/applets/applet_cabinet.h" +#include "core/hle/service/am/applets/applet_controller.h" #include "core/hle/service/am/applets/applet_mii_edit_types.h" #include "core/hle/service/am/applets/applet_profile_select.h" #include "core/hle/service/am/applets/applet_software_keyboard_types.h" @@ -35,6 +37,7 @@ #include "core/hle/service/caps/caps_su.h" #include "core/hle/service/caps/caps_types.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" @@ -73,7 +76,7 @@ IWindowController::IWindowController(Core::System& system_) static const FunctionInfo functions[] = { {0, nullptr, "CreateWindow"}, {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, - {2, nullptr, "GetAppletResourceUserIdOfCallerApplet"}, + {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, {11, nullptr, "ReleaseForegroundRights"}, {12, nullptr, "RejectToChangeIntoBackground"}, @@ -97,6 +100,16 @@ void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { rb.Push(process_id); } +void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { + const u64 process_id = 0; + + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(process_id); +} + void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; @@ -1565,7 +1578,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) {6, nullptr, "GetPopInteractiveInDataEvent"}, {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, - {12, nullptr, "GetMainAppletIdentityInfo"}, + {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, {13, nullptr, "CanUseApplicationCore"}, {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, {15, nullptr, "GetMainAppletApplicationControlProperty"}, @@ -1609,6 +1622,9 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) case Applets::AppletId::SoftwareKeyboard: PushInShowSoftwareKeyboard(); break; + case Applets::AppletId::Controller: + PushInShowController(); + break; default: break; } @@ -1666,13 +1682,33 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { rb.PushRaw(applet_info); } +void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { + struct AppletIdentityInfo { + Applets::AppletId applet_id; + INSERT_PADDING_BYTES(0x4); + u64 application_id; + }; + static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); + + LOG_WARNING(Service_AM, "(STUBBED) called"); + + const AppletIdentityInfo applet_info{ + .applet_id = Applets::AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.PushRaw(applet_info); +} + void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { struct AppletIdentityInfo { Applets::AppletId applet_id; INSERT_PADDING_BYTES(0x4); u64 application_id; }; - + static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); LOG_WARNING(Service_AM, "(STUBBED) called"); const AppletIdentityInfo applet_info{ @@ -1737,6 +1773,55 @@ void ILibraryAppletSelfAccessor::PushInShowAlbum() { queue_data.emplace_back(std::move(settings_data)); } +void ILibraryAppletSelfAccessor::PushInShowController() { + const Applets::CommonArguments common_args = { + .arguments_version = Applets::CommonArgumentVersion::Version3, + .size = Applets::CommonArgumentSize::Version3, + .library_version = static_cast(Applets::ControllerAppletVersion::Version8), + .theme_color = Applets::ThemeColor::BasicBlack, + .play_startup_sound = true, + .system_tick = system.CoreTiming().GetClockTicks(), + }; + + Applets::ControllerSupportArgNew user_args = { + .header = {.player_count_min = 1, + .player_count_max = 4, + .enable_take_over_connection = true, + .enable_left_justify = false, + .enable_permit_joy_dual = true, + .enable_single_mode = false, + .enable_identification_color = false}, + .identification_colors = {}, + .enable_explain_text = false, + .explain_text = {}, + }; + + Applets::ControllerSupportArgPrivate private_args = { + .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate), + .arg_size = sizeof(Applets::ControllerSupportArgNew), + .is_home_menu = true, + .flag_1 = true, + .mode = Applets::ControllerSupportMode::ShowControllerSupport, + .caller = Applets::ControllerSupportCaller:: + Application, // switchbrew: Always zero except with + // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem, + // which sets this to the input param + .style_set = Core::HID::NpadStyleSet::None, + .joy_hold_type = 0, + }; + std::vector common_args_data(sizeof(common_args)); + std::vector private_args_data(sizeof(private_args)); + std::vector user_args_data(sizeof(user_args)); + + std::memcpy(common_args_data.data(), &common_args, sizeof(common_args)); + std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); + std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); + + queue_data.emplace_back(std::move(common_args_data)); + queue_data.emplace_back(std::move(private_args_data)); + queue_data.emplace_back(std::move(user_args_data)); +} + void ILibraryAppletSelfAccessor::PushInShowCabinetData() { const Applets::CommonArguments arguments{ .arguments_version = Applets::CommonArgumentVersion::Version3, diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 8f8cb8a9e..905a71b9f 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -87,6 +87,7 @@ public: private: void GetAppletResourceUserId(HLERequestContext& ctx); + void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); void AcquireForegroundRights(HLERequestContext& ctx); }; @@ -345,6 +346,7 @@ private: void PopInData(HLERequestContext& ctx); void PushOutData(HLERequestContext& ctx); void GetLibraryAppletInfo(HLERequestContext& ctx); + void GetMainAppletIdentityInfo(HLERequestContext& ctx); void ExitProcessAndReturn(HLERequestContext& ctx); void GetCallerAppletIdentityInfo(HLERequestContext& ctx); void GetDesirableKeyboardLayout(HLERequestContext& ctx); @@ -355,6 +357,7 @@ private: void PushInShowCabinetData(); void PushInShowMiiEditData(); void PushInShowSoftwareKeyboard(); + void PushInShowController(); std::deque> queue_data; }; diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h index f6c64f633..9f839f3d7 100644 --- a/src/core/hle/service/am/applets/applet_controller.h +++ b/src/core/hle/service/am/applets/applet_controller.h @@ -56,7 +56,7 @@ enum class ControllerSupportResult : u32 { struct ControllerSupportArgPrivate { u32 arg_private_size{}; u32 arg_size{}; - bool flag_0{}; + bool is_home_menu{}; bool flag_1{}; ControllerSupportMode mode{}; ControllerSupportCaller caller{}; diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 8069f75b7..c65e32489 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -127,7 +127,7 @@ public: private: void GetCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_BTM, "called"); + LOG_WARNING(Service_BTM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); @@ -263,13 +263,13 @@ public: explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "StartGamepadPairing"}, - {1, nullptr, "CancelGamepadPairing"}, + {0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"}, + {1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"}, {2, nullptr, "ClearGamepadPairingDatabase"}, {3, nullptr, "GetPairedGamepadCount"}, {4, nullptr, "EnableRadio"}, {5, nullptr, "DisableRadio"}, - {6, nullptr, "GetRadioOnOff"}, + {6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"}, {7, nullptr, "AcquireRadioEvent"}, {8, nullptr, "AcquireGamepadPairingEvent"}, {9, nullptr, "IsGamepadPairingStarted"}, @@ -280,18 +280,58 @@ public: {14, nullptr, "AcquireAudioDeviceConnectionEvent"}, {15, nullptr, "ConnectAudioDevice"}, {16, nullptr, "IsConnectingAudioDevice"}, - {17, nullptr, "GetConnectedAudioDevices"}, + {17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"}, {18, nullptr, "DisconnectAudioDevice"}, {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, {20, nullptr, "GetPairedAudioDevices"}, {21, nullptr, "RemoveAudioDevicePairing"}, - {22, nullptr, "RequestAudioDeviceConnectionRejection"}, - {23, nullptr, "CancelAudioDeviceConnectionRejection"} + {22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"}, + {23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"} }; // clang-format on RegisterHandlers(functions); } + +private: + void IsRadioEnabled(HLERequestContext& ctx) { + LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(true); + } + + void StartGamepadPairing(HLERequestContext& ctx) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void CancelGamepadPairing(HLERequestContext& ctx) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void GetConnectedAudioDevices(HLERequestContext& ctx) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + } + + void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } }; class BTM_SYS final : public ServiceFramework { @@ -308,7 +348,7 @@ public: private: void GetCore(HLERequestContext& ctx) { - LOG_DEBUG(Service_BTM, "called"); + LOG_WARNING(Service_BTM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index d46bf917e..127af2b82 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -344,6 +344,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, Common::Input::PollingMode::Active); } + SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory); hid_core.SetLastActiveController(npad_id); @@ -1726,4 +1727,19 @@ const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( } } +Controller_NPad::AppletDetailedUiType Controller_NPad::GetAppletDetailedUiType( + Core::HID::NpadIdType npad_id) { + + auto controller = GetControllerFromNpadIdType(npad_id); + auto shared_memory = controller.shared_memory; + Service::HID::Controller_NPad::AppletFooterUiType applet_footer_type = + shared_memory->applet_footer_type; + + Controller_NPad::AppletDetailedUiType detailed_ui_type{ + .ui_variant = 0, + .footer = applet_footer_type, + }; + return detailed_ui_type; +} + } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index e23b4986c..cd93abdd1 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -78,6 +78,46 @@ public: MaxActivationMode = 3, }; + // This is nn::hid::system::AppletFooterUiAttributesSet + struct AppletFooterUiAttributes { + INSERT_PADDING_BYTES(0x4); + }; + + // This is nn::hid::system::AppletFooterUiType + enum class AppletFooterUiType : u8 { + None = 0, + HandheldNone = 1, + HandheldJoyConLeftOnly = 2, + HandheldJoyConRightOnly = 3, + HandheldJoyConLeftJoyConRight = 4, + JoyDual = 5, + JoyDualLeftOnly = 6, + JoyDualRightOnly = 7, + JoyLeftHorizontal = 8, + JoyLeftVertical = 9, + JoyRightHorizontal = 10, + JoyRightVertical = 11, + SwitchProController = 12, + CompatibleProController = 13, + CompatibleJoyCon = 14, + LarkHvc1 = 15, + LarkHvc2 = 16, + LarkNesLeft = 17, + LarkNesRight = 18, + Lucia = 19, + Verification = 20, + Lagon = 21, + }; + + using AppletFooterUiVariant = u8; + + // This is "nn::hid::system::AppletDetailedUiType". + struct AppletDetailedUiType { + AppletFooterUiVariant ui_variant; + INSERT_PADDING_BYTES(0x2); + AppletFooterUiType footer; + }; + static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); // This is nn::hid::NpadCommunicationMode enum class NpadCommunicationMode : u64 { Mode_5ms = 0, @@ -203,6 +243,7 @@ public: static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); static Result VerifyValidSixAxisSensorHandle( const Core::HID::SixAxisSensorHandle& device_handle); + AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); private: static constexpr std::size_t NPAD_COUNT = 10; @@ -360,37 +401,6 @@ private: static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, "NfcXcdDeviceHandleStateImpl is an invalid size"); - // This is nn::hid::system::AppletFooterUiAttributesSet - struct AppletFooterUiAttributes { - INSERT_PADDING_BYTES(0x4); - }; - - // This is nn::hid::system::AppletFooterUiType - enum class AppletFooterUiType : u8 { - None = 0, - HandheldNone = 1, - HandheldJoyConLeftOnly = 2, - HandheldJoyConRightOnly = 3, - HandheldJoyConLeftJoyConRight = 4, - JoyDual = 5, - JoyDualLeftOnly = 6, - JoyDualRightOnly = 7, - JoyLeftHorizontal = 8, - JoyLeftVertical = 9, - JoyRightHorizontal = 10, - JoyRightVertical = 11, - SwitchProController = 12, - CompatibleProController = 13, - CompatibleJoyCon = 14, - LarkHvc1 = 15, - LarkHvc2 = 16, - LarkNesLeft = 17, - LarkNesRight = 18, - Lucia = 19, - Verification = 20, - Lagon = 21, - }; - // This is nn::hid::NpadLarkType enum class NpadLarkType : u32 { Invalid, diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 0be6a7186..56f26a14a 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -1222,8 +1222,8 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) { controller.SetNpadMode(new_npad_id, parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, - parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, + parameters.applet_resource_user_id); // Spams a lot when controller applet is open IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 83cfadada..6f1902ee5 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -36,24 +36,24 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptrGetController(HidController::NPad) + .ApplyNpadSystemCommonPolicy(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IHidSystemServer::GetNpadFullKeyGripColor(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + Core::HID::NpadColor left_color{}; + Core::HID::NpadColor right_color{}; + // TODO: Get colors from Npad + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.PushRaw(left_color); + rb.PushRaw(right_color); +} + +void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + LOG_INFO(Service_HID, "(STUBBED) called"); + + Core::HID::NpadStyleSet supported_styleset = + GetResourceManager() + ->GetController(HidController::NPad) + .GetSupportedStyleSet() + .raw; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(supported_styleset); +} + +void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + LOG_INFO(Service_HID, "(STUBBED) called"); + + Core::HID::NpadStyleSet supported_styleset = + GetResourceManager() + ->GetController(HidController::NPad) + .GetSupportedStyleSet() + .raw; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(supported_styleset); +} + +void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + const Service::HID::Controller_NPad::AppletDetailedUiType detailed_ui_type = + GetResourceManager() + ->GetController(HidController::NPad) + .GetAppletDetailedUiType(npad_id_type); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushRaw(detailed_ui_type); +} + +void IHidSystemServer::GetNpadInterfaceType(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); +} + +void IHidSystemServer::GetNpadLeftRightInterfaceType(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); + rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth); +} + +void IHidSystemServer::HasBattery(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(false); +} + +void IHidSystemServer::HasLeftRightBattery(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto npad_id_type{rp.PopEnum()}; + + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running + + struct LeftRightBattery { + bool left; + bool right; + }; + + LeftRightBattery left_right_battery{ + .left = false, + .right = false, + }; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushRaw(left_right_battery); +} + void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto npad_id_type{rp.PopEnum()}; - LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type); + LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}", + npad_id_type); // Spams a lot when controller applet is running const std::vector unique_pads{}; - ctx.WriteBuffer(unique_pads); + if (!unique_pads.empty()) { + ctx.WriteBuffer(unique_pads); + } IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); rb.Push(static_cast(unique_pads.size())); } +void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + LOG_WARNING(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IHidSystemServer::AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx) { + LOG_INFO(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent()); +} + +void IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx) { + LOG_INFO(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent()); +} + +void IHidSystemServer::GetRegisteredDevices(HLERequestContext& ctx) { + LOG_WARNING(Service_HID, "(STUBBED) called"); + + struct RegisterData { + std::array data; + }; + static_assert(sizeof(RegisterData) == 0x68, "RegisterData is an invalid size"); + std::vector registered_devices{}; + + if (!registered_devices.empty()) { + ctx.WriteBuffer(registered_devices); + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(registered_devices.size()); +} + +void IHidSystemServer::AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx) { + LOG_WARNING(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.PushCopyObjects(unique_pad_connection_event->GetReadableEvent()); + rb.Push(ResultSuccess); +} + +void IHidSystemServer::GetUniquePadIds(HLERequestContext& ctx) { + LOG_WARNING(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(0); +} + void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) { LOG_INFO(Service_AM, "called"); @@ -279,6 +501,31 @@ void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) { rb.Push(is_enabled); } +void IHidSystemServer::IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx) { + const bool button_pressed = false; + + LOG_DEBUG(Service_HID, "(STUBBED) called, is_enabled={}", + button_pressed); // Spams a lot when controller applet is open + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(button_pressed); +} + +void IHidSystemServer::InitializeFirmwareUpdate(HLERequestContext& ctx) { + LOG_WARNING(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx) { + LOG_WARNING(Service_HID, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) { LOG_WARNING(Service_HID, "(STUBBED) called"); diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index d4b3910fa..822d5e5b9 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h @@ -24,15 +24,38 @@ public: private: void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx); + void EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx); + void DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx); void GetLastActiveNpad(HLERequestContext& ctx); + void ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx); + void GetNpadFullKeyGripColor(HLERequestContext& ctx); + void GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx); + void SetSupportedNpadStyleSetAll(HLERequestContext& ctx); + void GetAppletDetailedUiType(HLERequestContext& ctx); + void GetNpadInterfaceType(HLERequestContext& ctx); + void GetNpadLeftRightInterfaceType(HLERequestContext& ctx); + void HasBattery(HLERequestContext& ctx); + void HasLeftRightBattery(HLERequestContext& ctx); void GetUniquePadsFromNpad(HLERequestContext& ctx); + void GetIrSensorState(HLERequestContext& ctx); + void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); + void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); + void GetRegisteredDevices(HLERequestContext& ctx); + void AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx); + void GetUniquePadIds(HLERequestContext& ctx); void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx); void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx); + void IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx); + void InitializeFirmwareUpdate(HLERequestContext& ctx); + void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); std::shared_ptr GetResourceManager(); + Kernel::KEvent* acquire_connection_trigger_timeout_event; + Kernel::KEvent* acquire_device_registered_event; Kernel::KEvent* joy_detach_event; + Kernel::KEvent* unique_pad_connection_event; KernelHelpers::ServiceContext service_context; std::shared_ptr resource_manager; }; diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 7927f8264..961f89a14 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -115,12 +115,20 @@ public: {400, nullptr, "InitializeSystem"}, {401, nullptr, "FinalizeSystem"}, {402, nullptr, "SetOperationMode"}, - {403, nullptr, "InitializeSystem2"}, + {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"}, }; // clang-format on RegisterHandlers(functions); } + +private: + void InitializeSystem2(HLERequestContext& ctx) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } }; class IUserLocalCommunicationService final diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index ec3af80af..19c667b42 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -431,8 +431,7 @@ void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) { u8 battery_percentage_flag{1}; - LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}", - battery_percentage_flag); + LOG_DEBUG(Service_SET, "(STUBBED) called, battery_percentage_flag={}", battery_percentage_flag); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -492,6 +491,29 @@ void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) { rb.PushEnum(ChineseTraditionalInputMethod::Unknown0); } +void SET_SYS::GetHomeMenuScheme(HLERequestContext& ctx) { + LOG_DEBUG(Service_SET, "(STUBBED) called"); + + const HomeMenuScheme default_color = { + .main = 0xFF323232, + .back = 0xFF323232, + .sub = 0xFFFFFFFF, + .bezel = 0xFFFFFFFF, + .extra = 0xFF000000, + }; + + IPC::ResponseBuilder rb{ctx, 7}; + rb.Push(ResultSuccess); + rb.PushRaw(default_color); +} + +void SET_SYS::GetHomeMenuSchemeModel(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); +} void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) { LOG_WARNING(Service_SET, "(STUBBED) called"); @@ -674,7 +696,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {171, nullptr, "SetChineseTraditionalInputMethod"}, {172, nullptr, "GetPtmCycleCountReliability"}, {173, nullptr, "SetPtmCycleCountReliability"}, - {174, nullptr, "GetHomeMenuScheme"}, + {174, &SET_SYS::GetHomeMenuScheme, "GetHomeMenuScheme"}, {175, nullptr, "GetThemeSettings"}, {176, nullptr, "SetThemeSettings"}, {177, nullptr, "GetThemeKey"}, @@ -685,7 +707,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {182, nullptr, "SetT"}, {183, nullptr, "GetPlatformRegion"}, {184, nullptr, "SetPlatformRegion"}, - {185, nullptr, "GetHomeMenuSchemeModel"}, + {185, &SET_SYS::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"}, {186, nullptr, "GetMemoryUsageRateFlag"}, {187, nullptr, "GetTouchScreenMode"}, {188, nullptr, "SetTouchScreenMode"}, diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index c7dba2a9e..93023c6dd 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -269,6 +269,16 @@ private: }; static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect 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"); + void SetLanguageCode(HLERequestContext& ctx); void GetFirmwareVersion(HLERequestContext& ctx); void GetFirmwareVersion2(HLERequestContext& ctx); @@ -305,6 +315,8 @@ private: void GetKeyboardLayout(HLERequestContext& ctx); void GetChineseTraditionalInputMethod(HLERequestContext& ctx); void GetFieldTestingFlag(HLERequestContext& ctx); + void GetHomeMenuScheme(HLERequestContext& ctx); + void GetHomeMenuSchemeModel(HLERequestContext& ctx); AccountSettings account_settings{ .flags = {}, diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f077d7f9c..b0e995c52 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1574,6 +1574,7 @@ void GMainWindow::ConnectMenuEvents() { connect_menu(ui->action_Load_Cabinet_Formatter, [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); }); connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); + connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu); connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); // TAS @@ -1601,14 +1602,13 @@ void GMainWindow::UpdateMenuState() { ui->action_Pause, }; - const std::array applet_actions{ - ui->action_Load_Album, - ui->action_Load_Cabinet_Nickname_Owner, - ui->action_Load_Cabinet_Eraser, - ui->action_Load_Cabinet_Restorer, - ui->action_Load_Cabinet_Formatter, - ui->action_Load_Mii_Edit, - }; + const std::array applet_actions{ui->action_Load_Album, + ui->action_Load_Cabinet_Nickname_Owner, + ui->action_Load_Cabinet_Eraser, + ui->action_Load_Cabinet_Restorer, + ui->action_Load_Cabinet_Formatter, + ui->action_Load_Mii_Edit, + ui->action_Open_Controller_Menu}; for (QAction* action : running_actions) { action->setEnabled(emulation_running); @@ -4346,6 +4346,31 @@ void GMainWindow::OnMiiEdit() { BootGame(filename, MiiEditId); } +void GMainWindow::OnOpenControllerMenu() { + constexpr u64 ControllerAppletId = + static_cast(Service::AM::Applets::AppletProgramId::Controller); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); + if (!bis_system) { + QMessageBox::warning(this, tr("No firmware available"), + tr("Please install the firmware to use the Controller Menu.")); + return; + } + + auto controller_applet_nca = + bis_system->GetEntry(ControllerAppletId, FileSys::ContentRecordType::Program); + if (!controller_applet_nca) { + QMessageBox::warning(this, tr("Controller Applet"), + tr("Controller Menu is not available. Please reinstall firmware.")); + return; + } + + system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); + + const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); + UISettings::values.roms_path = QFileInfo(filename).path(); + BootGame(filename, ControllerAppletId); +} + void GMainWindow::OnCaptureScreenshot() { if (emu_thread == nullptr || !emu_thread->IsRunning()) { return; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index f9c6efe4f..19740cc52 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -402,6 +402,7 @@ private slots: void OnAlbum(); void OnCabinet(Service::NFP::CabinetMode mode); void OnMiiEdit(); + void OnOpenControllerMenu(); void OnCaptureScreenshot(); void OnReinitializeKeys(ReinitializeKeyBehavior behavior); void OnLanguageChanged(const QString& locale); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 88684ffb5..e53f9951e 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -25,7 +25,7 @@ - + 0 @@ -36,7 +36,7 @@ 0 0 1280 - 26 + 21 @@ -162,6 +162,7 @@ + @@ -382,9 +383,9 @@ - - Open &Album - + + Open &Album + @@ -407,9 +408,9 @@ - - Open &Mii Editor - + + Open &Mii Editor + @@ -454,6 +455,11 @@ R&ecord + + + Open &Controller Menu + +