Compare commits

...

6 Commits

Author SHA1 Message Date
german77 d4db71a4aa fix settings 2024-01-22 12:02:26 -06:00
german77 fd413f45a8 moar stubs 2024-01-22 12:02:22 -06:00
german77 17fb8f2f29 service: Add even more stubs for Qlaunch 2024-01-22 12:01:08 -06:00
german77 7486e214bf service: Add stubs for Qlaunch 2024-01-22 12:00:26 -06:00
german77 ab6ed38ea8 service: notif: Implement notif:s 2024-01-22 12:00:25 -06:00
german77 d97de43996 service: bcat: Implement news service for Qlaunch 2024-01-22 12:00:25 -06:00
39 changed files with 1780 additions and 89 deletions

View File

@ -96,9 +96,10 @@ public:
{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
{134, nullptr, "RefreshNintendoAccountVerificationUrlCache"}, // 9.0.0+
{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{140, &IManagerForSystemService::GetNetworkServiceLicenseCache, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{143, &IManagerForSystemService::Unknown143, "Unknown143"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
@ -114,6 +115,24 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetNetworkServiceLicenseCache(HLERequestContext& ctx) {
LOG_ERROR(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.Push<u64>(0);
rb.Push<u64>(0);
}
void Unknown143(HLERequestContext& ctx) {
LOG_ERROR(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.Push<u64>(0);
rb.Push<u64>(0);
}
};
// 3.0.0+

View File

@ -354,7 +354,7 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
{60, &ISelfController::OverrideAutoSleepTimeAndDimmingTime, "OverrideAutoSleepTimeAndDimmingTime"},
{61, nullptr, "SetMediaPlaybackState"},
{62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
{63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
@ -366,7 +366,7 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
{69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
{70, nullptr, "ReportMultimediaError"},
{71, nullptr, "GetCurrentIlluminanceEx"},
{72, nullptr, "SetInputDetectionPolicy"},
{72, &ISelfController::SetInputDetectionPolicy, "SetInputDetectionPolicy"},
{80, nullptr, "SetWirelessPriorityMode"},
{90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
{91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
@ -628,6 +628,18 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISelfController::OverrideAutoSleepTimeAndDimmingTime(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto a = rp.Pop<u32>();
const auto b = rp.Pop<u32>();
const auto c = rp.Pop<u32>();
const auto d = rp.Pop<u32>();
LOG_WARNING(Service_AM, "(STUBBED) called, a={}, b={}, c={}, d={}",a,b,c,d);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
idle_time_detection_extension = rp.Pop<u32>();
@ -681,6 +693,13 @@ void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
rb.Push(is_auto_sleep_disabled);
}
void ISelfController::SetInputDetectionPolicy(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called.");
@ -890,7 +909,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{20, nullptr, "PushToGeneralChannel"},
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
{32, nullptr, "GetWriterLockAccessorEx"},
{32, &ICommonStateGetter::GetWriterLockAccessorEx, "GetWriterLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
@ -914,7 +933,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
{110, nullptr, "OpenMyGpuErrorHandler"},
{120, nullptr, "GetAppletLaunchedHistory"},
{200, nullptr, "GetOperationModeSystemInfo"},
{200, &ICommonStateGetter::GetOperationModeSystemInfo, "GetOperationModeSystemInfo"},
{300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
{400, nullptr, "ActivateMigrationService"},
{401, nullptr, "DeactivateMigrationService"},
@ -1010,6 +1029,15 @@ void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
}
void ICommonStateGetter::GetWriterLockAccessorEx(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ILockAccessor>(system);
}
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
@ -1104,6 +1132,14 @@ void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext&
rb.Push(ResultSuccess);
}
void ICommonStateGetter::GetOperationModeSystemInfo(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@ -1601,7 +1637,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
{120, nullptr, "GetLaunchStorageInfoForDebug"},
{130, nullptr, "GetGpuErrorDetectedSystemEvent"},
{140, nullptr, "SetApplicationMemoryReservation"},
{150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
{150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
};
// clang-format on
RegisterHandlers(functions);
@ -1622,7 +1658,11 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
case Applets::AppletId::Controller:
PushInShowController();
break;
case Applets::AppletId::MyPage:
PushInShowMyPageData();
break;
default:
PushInShow();
break;
}
}
@ -1819,6 +1859,30 @@ void ILibraryAppletSelfAccessor::PushInShowController() {
queue_data.emplace_back(std::move(user_args_data));
}
void ILibraryAppletSelfAccessor::PushInShowMyPageData() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version1,
.size = Applets::CommonArgumentSize::Version3,
.library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
.theme_color = Applets::ThemeColor::BasicBlack,
.play_startup_sound = true,
.system_tick = system.CoreTiming().GetClockTicks(),
};
std::vector<u8> argument_data(sizeof(arguments));
std::vector<u8> settings_data{0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE,
0x9E, 0xF8, 0xAF, 0xB1, 0xE8, 0x95, 0x90, 0x33, 0x6C,
0x0B, 0x22, 0x70, 0x07, 0xF4, 0xBB, 0x00};
settings_data.resize(0x10a8);
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
queue_data.emplace_back(std::move(argument_data));
queue_data.emplace_back(std::move(settings_data));
}
void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version3,
@ -1848,6 +1912,35 @@ void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
queue_data.emplace_back(std::move(settings_data));
}
void ILibraryAppletSelfAccessor::PushInShow() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version3,
.size = Applets::CommonArgumentSize::Version3,
.library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
.theme_color = Applets::ThemeColor::BasicBlack,
.play_startup_sound = true,
.system_tick = system.CoreTiming().GetClockTicks(),
};
const Applets::StartParamForAmiiboSettings amiibo_settings{
.param_1 = 0,
.applet_mode = {},
.flags = {},
.amiibo_settings_1 = 0,
.device_handle = 0,
.tag_info{},
.register_info{},
.amiibo_settings_3{},
};
std::vector<u8> argument_data(sizeof(arguments));
std::vector<u8> settings_data(sizeof(amiibo_settings));
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
queue_data.emplace_back(std::move(argument_data));
queue_data.emplace_back(std::move(settings_data));
}
void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
struct MiiEditV3 {
Applets::MiiEditAppletInputCommon common;
@ -2556,14 +2649,14 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
// clang-format off
static const FunctionInfo functions[] = {
{10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
{11, nullptr, "LockForeground"},
{12, nullptr, "UnlockForeground"},
{11, &IHomeMenuFunctions::LockForeground, "LockForeground"},
{12, &IHomeMenuFunctions::UnlockForeground, "UnlockForeground"},
{20, nullptr, "PopFromGeneralChannel"},
{21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
{31, nullptr, "GetWriterLockAccessorEx"},
{40, nullptr, "IsSleepEnabled"},
{41, nullptr, "IsRebootEnabled"},
{41, &IHomeMenuFunctions::IsRebootEnabled, "IsRebootEnabled"},
{50, nullptr, "LaunchSystemApplet"},
{51, nullptr, "LaunchStarter"},
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
@ -2590,6 +2683,19 @@ void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void IHomeMenuFunctions::LockForeground(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHomeMenuFunctions::UnlockForeground(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
@ -2598,8 +2704,65 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
}
void IHomeMenuFunctions::IsRebootEnabled(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(true);
}
ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_)
: ServiceFramework{system_, "ICradleFirmwareUpdater"}, service_context{system,
"IHomeMenuFunctions"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "StartUpdate"},
{1, &ICradleFirmwareUpdater::FinishUpdate, "FinishUpdate"},
{2, &ICradleFirmwareUpdater::GetCradleDeviceInfo, "GetCradleDeviceInfo"},
{3, &ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent, "GetCradleDeviceInfoChangeEvent"},
{4, nullptr, "GetUpdateProgressInfo"},
{5, nullptr, "GetLastInternalResult"},
};
// clang-format on
RegisterHandlers(functions);
cradle_device_info_event =
service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
}
ICradleFirmwareUpdater::~ICradleFirmwareUpdater() {
service_context.CloseEvent(cradle_device_info_event);
}
void ICradleFirmwareUpdater::FinishUpdate(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ICradleFirmwareUpdater::GetCradleDeviceInfo(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 5};
rb.Push(ResultSuccess);
rb.Push<u64>(0);
rb.Push<u32>(0);
}
void ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(cradle_device_info_event->GetReadableEvent());
}
IGlobalStateController::IGlobalStateController(Core::System& system_)
: ServiceFramework{system_, "IGlobalStateController"} {
: ServiceFramework{system_, "IGlobalStateController"},
service_context{system_, "IGlobalStateController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestToEnterSleep"},
@ -2608,21 +2771,57 @@ IGlobalStateController::IGlobalStateController(Core::System& system_)
{3, nullptr, "StartShutdownSequence"},
{4, nullptr, "StartRebootSequence"},
{9, nullptr, "IsAutoPowerDownRequested"},
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
{10, &IGlobalStateController::LoadAndApplyIdlePolicySettings, "LoadAndApplyIdlePolicySettings"},
{11, nullptr, "NotifyCecSettingsChanged"},
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
{13, nullptr, "UpdateDefaultDisplayResolution"},
{14, nullptr, "ShouldSleepOnBoot"},
{15, nullptr, "GetHdcpAuthenticationFailedEvent"},
{30, nullptr, "OpenCradleFirmwareUpdater"},
{14, &IGlobalStateController::ShouldSleepOnBoot, "ShouldSleepOnBoot"},
{15, &IGlobalStateController::GetHdcpAuthenticationFailedEvent, "GetHdcpAuthenticationFailedEvent"},
{30, &IGlobalStateController::OpenCradleFirmwareUpdater, "OpenCradleFirmwareUpdater"},
};
// clang-format on
RegisterHandlers(functions);
hdcp_authentification_failed_event =
service_context.CreateEvent("IGlobalStateController::HdcpAuthenticationFailedEvent");
}
IGlobalStateController::~IGlobalStateController() = default;
void IGlobalStateController::LoadAndApplyIdlePolicySettings(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IGlobalStateController::ShouldSleepOnBoot(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void IGlobalStateController::GetHdcpAuthenticationFailedEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(hdcp_authentification_failed_event->GetReadableEvent());
}
void IGlobalStateController::OpenCradleFirmwareUpdater(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ICradleFirmwareUpdater>(system);
}
IApplicationCreator::IApplicationCreator(Core::System& system_)
: ServiceFramework{system_, "IApplicationCreator"} {
// clang-format off

View File

@ -163,11 +163,13 @@ private:
void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
void SetHandlesRequestToDisplay(HLERequestContext& ctx);
void ApproveToDisplay(HLERequestContext& ctx);
void OverrideAutoSleepTimeAndDimmingTime(HLERequestContext& ctx);
void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
void ReportUserIsActive(HLERequestContext& ctx);
void SetAutoSleepDisabled(HLERequestContext& ctx);
void IsAutoSleepDisabled(HLERequestContext& ctx);
void SetInputDetectionPolicy(HLERequestContext& ctx);
void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
@ -258,6 +260,7 @@ private:
void RequestToAcquireSleepLock(HLERequestContext& ctx);
void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
void GetReaderLockAccessorEx(HLERequestContext& ctx);
void GetWriterLockAccessorEx(HLERequestContext& ctx);
void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
void GetOperationMode(HLERequestContext& ctx);
void GetPerformanceMode(HLERequestContext& ctx);
@ -271,6 +274,7 @@ private:
void SetCpuBoostMode(HLERequestContext& ctx);
void GetBuiltInDisplayType(HLERequestContext& ctx);
void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
void GetOperationModeSystemInfo(HLERequestContext& ctx);
void GetSettingsPlatformRegion(HLERequestContext& ctx);
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
@ -354,7 +358,9 @@ private:
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
void PushInShowAlbum();
void PushInShowMyPageData();
void PushInShowCabinetData();
void PushInShow();
void PushInShowMiiEditData();
void PushInShowSoftwareKeyboard();
void PushInShowController();
@ -430,17 +436,44 @@ public:
private:
void RequestToGetForeground(HLERequestContext& ctx);
void LockForeground(HLERequestContext& ctx);
void UnlockForeground(HLERequestContext& ctx);
void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
void IsRebootEnabled(HLERequestContext& ctx);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* pop_from_general_channel_event;
};
class ICradleFirmwareUpdater final : public ServiceFramework<ICradleFirmwareUpdater> {
public:
explicit ICradleFirmwareUpdater(Core::System& system_);
~ICradleFirmwareUpdater() override;
private:
void FinishUpdate(HLERequestContext& ctx);
void GetCradleDeviceInfo(HLERequestContext& ctx);
void GetCradleDeviceInfoChangeEvent(HLERequestContext& ctx);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* cradle_device_info_event;
};
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
public:
explicit IGlobalStateController(Core::System& system_);
~IGlobalStateController() override;
private:
void LoadAndApplyIdlePolicySettings(HLERequestContext& ctx);
void ShouldSleepOnBoot(HLERequestContext& ctx);
void GetHdcpAuthenticationFailedEvent(HLERequestContext& ctx);
void OpenCradleFirmwareUpdater(HLERequestContext& ctx);
Kernel::KEvent* hdcp_authentification_failed_event;
KernelHelpers::ServiceContext service_context;
};
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {

View File

@ -138,6 +138,118 @@ private:
std::shared_ptr<AppletMessageQueue> msg_queue;
};
class IOverlayAppletProxy final : public ServiceFramework<IOverlayAppletProxy> {
public:
explicit IOverlayAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
std::shared_ptr<AppletMessageQueue> msg_queue_,
Core::System& system_)
: ServiceFramework{system_, "IOverlayAppletProxy"}, nvnflinger{nvnflinger_},
msg_queue{std::move(msg_queue_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IOverlayAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
{1, &IOverlayAppletProxy::GetSelfController, "GetSelfController"},
{2, &IOverlayAppletProxy::GetWindowController, "GetWindowController"},
{3, &IOverlayAppletProxy::GetAudioController, "GetAudioController"},
{4, &IOverlayAppletProxy::GetDisplayController, "GetDisplayController"},
{10, &IOverlayAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
{11, &IOverlayAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &IOverlayAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
{21, &IOverlayAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
{22, nullptr, "GetHomeMenuFunctions"},
{23, nullptr, "GetGlobalStateController"},
{1000, &IOverlayAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetCommonStateGetter(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
}
void GetSelfController(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
}
void GetWindowController(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IWindowController>(system);
}
void GetAudioController(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAudioController>(system);
}
void GetDisplayController(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IDisplayController>(system);
}
void GetProcessWindingController(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IProcessWindingController>(system);
}
void GetLibraryAppletCreator(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ILibraryAppletCreator>(system);
}
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
}
void GetAppletCommonFunctions(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAppletCommonFunctions>(system);
}
void GetDebugFunctions(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IDebugFunctions>(system);
}
Nvnflinger::Nvnflinger& nvnflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;
};
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
public:
explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
@ -282,6 +394,14 @@ void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system);
}
void AppletAE::OpenOverlayAppletProxy(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IOverlayAppletProxy>(nvnflinger, msg_queue, system);
}
AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
: ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{
@ -291,7 +411,7 @@ AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
{200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"},
{201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"},
{300, nullptr, "OpenOverlayAppletProxy"},
{300, &AppletAE::OpenOverlayAppletProxy, "OpenOverlayAppletProxy"},
{350, nullptr, "OpenSystemApplicationProxy"},
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
{410, nullptr, "GetSystemAppletControllerForDebug"},

View File

@ -32,6 +32,7 @@ private:
void OpenSystemAppletProxy(HLERequestContext& ctx);
void OpenLibraryAppletProxy(HLERequestContext& ctx);
void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
void OpenOverlayAppletProxy(HLERequestContext& ctx);
Nvnflinger::Nvnflinger& nvnflinger;
std::shared_ptr<AppletMessageQueue> msg_queue;

View File

@ -7,7 +7,8 @@
namespace Service::Audio {
AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
AudCtl::AudCtl(Core::System& system_)
: ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"},
@ -44,7 +45,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"},
{34, nullptr, "AcquireTargetNotification"},
{34, &AudCtl::AcquireTargetNotification, "AcquireTargetNotification"},
{35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{37, nullptr, "SetHearingProtectionSafeguardEnabled"},
@ -68,6 +69,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
// clang-format on
RegisterHandlers(functions);
notification_event =
service_context.CreateEvent("audctl:NotificationEvent");
}
AudCtl::~AudCtl() = default;
@ -134,4 +138,12 @@ void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
rb.Push<u8>(is_speaker_auto_mute_enabled);
}
void AudCtl::AcquireTargetNotification(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(notification_event->GetReadableEvent());
}
} // namespace Service::Audio

View File

@ -4,6 +4,7 @@
#pragma once
#include "core/hle/service/service.h"
#include "core/hle/service/kernel_helpers.h"
namespace Core {
class System;
@ -41,6 +42,11 @@ private:
void GetOutputModeSetting(HLERequestContext& ctx);
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void AcquireTargetNotification(HLERequestContext& ctx);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* notification_event;
};
} // namespace Service::Audio

View File

@ -147,7 +147,7 @@ public:
{30202, nullptr, "BlockDeliveryTask"},
{30203, nullptr, "UnblockDeliveryTask"},
{30210, nullptr, "SetDeliveryTaskTimer"},
{30300, nullptr, "RegisterSystemApplicationDeliveryTasks"},
{30300, &IBcatService::RegisterSystemApplicationDeliveryTasks, "RegisterSystemApplicationDeliveryTasks"},
{90100, nullptr, "EnumerateBackgroundDeliveryTask"},
{90101, nullptr, "Unknown90101"},
{90200, nullptr, "GetDeliveryList"},
@ -234,6 +234,13 @@ private:
rb.Push(ResultSuccess);
}
void RegisterSystemApplicationDeliveryTasks(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ClearDeliveryCacheStorage(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto title_id = rp.PopRaw<u64>();
@ -584,6 +591,287 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
Module::Interface::~Interface() = default;
class INewsService final : public ServiceFramework<INewsService> {
public:
explicit INewsService(Core::System& system_) : ServiceFramework{system_, "INewsService"} {
// clang-format off
static const FunctionInfo functions[] = {
{10100, &INewsService::PostLocalNews, "PostLocalNews"},
{20100, nullptr, "SetPassphrase"},
{30100, &INewsService::GetSubscriptionStatus, "GetSubscriptionStatus"},
{30101, nullptr, "GetTopicList"},
{30110, nullptr, "Unknown30110"},
{30200, &INewsService::IsSystemUpdateRequired, "IsSystemUpdateRequired"},
{30201, nullptr, "Unknown30201"},
{30210, nullptr, "Unknown30210"},
{30300, nullptr, "RequestImmediateReception"},
{30400, nullptr, "DecodeArchiveFile"},
{30500, nullptr, "Unknown30500"},
{30900, nullptr, "Unknown30900"},
{30901, nullptr, "Unknown30901"},
{30902, nullptr, "Unknown30902"},
{40100, nullptr, "SetSubscriptionStatus"},
{40101, &INewsService::RequestAutoSubscription, "RequestAutoSubscription"},
{40200, nullptr, "ClearStorage"},
{40201, nullptr, "ClearSubscriptionStatusAll"},
{90100, nullptr, "GetNewsDatabaseDump"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void PostLocalNews(HLERequestContext& ctx) {
const auto buffer_data = ctx.ReadBuffer();
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetSubscriptionStatus(HLERequestContext& ctx) {
const auto buffer_data = ctx.ReadBuffer();
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void IsSystemUpdateRequired(HLERequestContext& ctx) {
LOG_WARNING(Service_BCAT, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void RequestAutoSubscription(HLERequestContext& ctx) {
LOG_WARNING(Service_BCAT, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class INewsDataService final : public ServiceFramework<INewsDataService> {
public:
explicit INewsDataService(Core::System& system_)
: ServiceFramework{system_, "INewsDataService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Open"},
{1, &INewsDataService::OpenWithNewsRecord, "OpenWithNewsRecordV1"},
{2, &INewsDataService::Read, "Read"},
{3, nullptr, "GetSize"},
{1001, nullptr, "OpenWithNewsRecord"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenWithNewsRecord(HLERequestContext& ctx) {
LOG_WARNING(Service_BCAT, "(STUBBED) called"
);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void Read(HLERequestContext& ctx) {
LOG_WARNING(Service_BCAT, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(0);
}
};
class INewsDatabaseService final : public ServiceFramework<INewsDatabaseService> {
public:
explicit INewsDatabaseService(Core::System& system_)
: ServiceFramework{system_, "INewsDatabaseService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetListV1"},
{1, &INewsDatabaseService::Count, "Count"},
{2, nullptr, "CountWithKey"},
{3, nullptr, "UpdateIntegerValue"},
{4, &INewsDatabaseService::UpdateIntegerValueWithAddition, "UpdateIntegerValueWithAddition"},
{5, nullptr, "UpdateStringValue"},
{1000, &INewsDatabaseService::GetList, "GetList"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void Count(HLERequestContext& ctx) {
const auto buffer_data = ctx.ReadBuffer();
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void UpdateIntegerValueWithAddition(HLERequestContext& ctx) {
const auto buffer_data = ctx.ReadBuffer();
const auto buffer_data2 = ctx.ReadBuffer();
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={} {}", buffer_data.size(), buffer_data2.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetList(HLERequestContext& ctx) {
const auto buffer_data = ctx.ReadBuffer();
const auto buffer_data2 = ctx.ReadBuffer();
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={} {}", buffer_data.size(),
buffer_data2.size());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
};
class INewlyArrivedEventHolder final : public ServiceFramework<INewlyArrivedEventHolder> {
public:
explicit INewlyArrivedEventHolder(Core::System& system_)
: ServiceFramework{system_, "INewlyArrivedEventHolder"},
service_context{system_, "INewlyArrivedEventHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &INewlyArrivedEventHolder::Get, "Get"},
};
// clang-format on
RegisterHandlers(functions);
arrived_event = service_context.CreateEvent("INewlyArrivedEventHolder::ArrivedEvent");
}
private:
void Get(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(arrived_event->GetReadableEvent());
}
Kernel::KEvent* arrived_event;
KernelHelpers::ServiceContext service_context;
};
class IOverwriteEventHolder final : public ServiceFramework<IOverwriteEventHolder> {
public:
explicit IOverwriteEventHolder(Core::System& system_)
: ServiceFramework{system_, "IOverwriteEventHolder"},
service_context{system_, "IOverwriteEventHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IOverwriteEventHolder::Get, "Get"},
};
// clang-format on
RegisterHandlers(functions);
overwrite_event = service_context.CreateEvent("IOverwriteEventHolder::OverwriteEvent");
}
private:
void Get(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(overwrite_event->GetReadableEvent());
}
Kernel::KEvent* overwrite_event;
KernelHelpers::ServiceContext service_context;
};
class News final : public ServiceFramework<News> {
public:
explicit News(Core::System& system_) : ServiceFramework{system_, "news:p"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &News::CreateNewsService, "CreateNewsService"},
{1, &News::CreateNewlyArrivedEventHolder, "CreateNewlyArrivedEventHolder"},
{2, &News::CreateNewsDataService, "CreateNewsDataService"},
{3, &News::CreateNewsDatabaseService, "CreateNewsDatabaseService"},
{4, &News::CreateOverwriteEventHolder, "CreateOverwriteEventHolder"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void CreateNewsService(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INewsService>(system);
}
void CreateNewlyArrivedEventHolder(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INewlyArrivedEventHolder>(system);
}
void CreateNewsDataService(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INewsDataService>(system);
}
void CreateNewsDatabaseService(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INewsDatabaseService>(system);
}
void CreateOverwriteEventHolder(HLERequestContext& ctx) {
LOG_INFO(Service_BCAT, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IOverwriteEventHolder>(system);
}
};
class MNPPSYS final : public ServiceFramework<MNPPSYS> {
public:
explicit MNPPSYS(Core::System& system_) : ServiceFramework{system_, "mnpp:sys"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown0"},
{100, nullptr, "Unknown100"},
{200, nullptr, "Unknown200"},
{300, nullptr, "Unknown300"},
{400, nullptr, "Unknown400"},
};
// clang-format on
RegisterHandlers(functions);
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
auto module = std::make_shared<Module>();
@ -600,6 +888,10 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService(
"bcat:s",
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s"));
server_manager->RegisterNamedService("news:p", std::make_shared<News>(system));
server_manager->RegisterNamedService("mnpp:sys", std::make_shared<MNPPSYS>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -93,7 +93,7 @@ public:
{31, nullptr, "EnableMcMode"},
{32, nullptr, "EnableLlrScan"},
{33, nullptr, "DisableLlrScan"},
{34, nullptr, "EnableRadio"},
{34, &BtDrv::EnableRadio, "EnableRadio"},
{35, nullptr, "SetVisibility"},
{36, nullptr, "EnableTbfcScan"},
{37, nullptr, "RegisterHidReportEvent"},
@ -195,6 +195,12 @@ public:
RegisterHandlers(functions);
}
private:
void EnableRadio(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
void LoopProcess(Core::System& system) {

View File

@ -154,8 +154,8 @@ public:
{11, nullptr, "RemoveDeviceInfo"},
{12, nullptr, "IncreaseDeviceInfoOrder"},
{13, nullptr, "LlrNotify"},
{14, nullptr, "EnableRadio"},
{15, nullptr, "DisableRadio"},
{14, &BTM::EnableRadio, "EnableRadio"},
{15, &BTM::DisableRadio, "DisableRadio"},
{16, nullptr, "HidDisconnect"},
{17, nullptr, "HidSetRetransmissionMode"},
{18, nullptr, "AcquireAwakeReqEvent"},
@ -230,6 +230,17 @@ public:
RegisterHandlers(functions);
}
private:
void EnableRadio(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void DisableRadio(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class BTM_DBG final : public ServiceFramework<BTM_DBG> {
@ -260,24 +271,25 @@ public:
class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
public:
explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} {
explicit IBtmSystemCore(Core::System& system_)
: ServiceFramework{system_, "IBtmSystemCore"}, service_context{system_, "IBtmSystemCore"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"},
{1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"},
{2, nullptr, "ClearGamepadPairingDatabase"},
{3, nullptr, "GetPairedGamepadCount"},
{4, nullptr, "EnableRadio"},
{5, nullptr, "DisableRadio"},
{4, &IBtmSystemCore::EnableRadio, "EnableRadio"},
{5, &IBtmSystemCore::DisableRadio, "DisableRadio"},
{6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"},
{7, nullptr, "AcquireRadioEvent"},
{7, &IBtmSystemCore::AcquireRadioEvent, "AcquireRadioEvent"},
{8, nullptr, "AcquireGamepadPairingEvent"},
{9, nullptr, "IsGamepadPairingStarted"},
{10, nullptr, "StartAudioDeviceDiscovery"},
{11, nullptr, "StopAudioDeviceDiscovery"},
{12, nullptr, "IsDiscoveryingAudioDevice"},
{13, nullptr, "GetDiscoveredAudioDevice"},
{14, nullptr, "AcquireAudioDeviceConnectionEvent"},
{14, &IBtmSystemCore::AcquireAudioDeviceConnectionEvent, "AcquireAudioDeviceConnectionEvent"},
{15, nullptr, "ConnectAudioDevice"},
{16, nullptr, "IsConnectingAudioDevice"},
{17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"},
@ -291,9 +303,21 @@ public:
// clang-format on
RegisterHandlers(functions);
radio_event = service_context.CreateEvent("IBtmSystemCore::RadioEvent");
audio_device_connection_event = service_context.CreateEvent("IBtmSystemCore::AudioDeviceConnectionEvent");
}
private:
void EnableRadio(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void DisableRadio(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IsRadioEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running
@ -331,7 +355,29 @@ private:
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} void AcquireRadioEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_BTM, "called");
radio_event->Signal();
IPC::ResponseBuilder rb{ ctx, 3, 1 };
rb.Push(ResultSuccess);
rb.Push(true);
rb.PushCopyObjects(radio_event->GetReadableEvent());
}
void AcquireAudioDeviceConnectionEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_BTM, "called");
IPC::ResponseBuilder rb{ctx, 3, 1};
rb.Push(ResultSuccess);
rb.Push(true);
rb.PushCopyObjects(audio_device_connection_event->GetReadableEvent());
}
Kernel::KEvent* radio_event;
Kernel::KEvent* audio_device_connection_event;
KernelHelpers::ServiceContext service_context;
};
class BTM_SYS final : public ServiceFramework<BTM_SYS> {

View File

@ -16,7 +16,7 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetAlbumFileCount"},
{1, nullptr, "GetAlbumFileList"},
{1, &IAlbumAccessorService::GetAlbumFileList, "GetAlbumFileList"},
{2, nullptr, "LoadAlbumFile"},
{3, &IAlbumAccessorService::DeleteAlbumFile, "DeleteAlbumFile"},
{4, nullptr, "StorageCopyAlbumFile"},
@ -62,6 +62,29 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
IAlbumAccessorService::~IAlbumAccessorService() = default;
void IAlbumAccessorService::GetAlbumFileList(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage{rp.PopEnum<AlbumStorage>()};
const auto album_entry_size{ctx.GetWriteBufferNumElements<AlbumEntry>()};
LOG_INFO(Service_Capture, "called, storage={}", storage);
std::vector<AlbumEntry> entries;
Result result = manager->GetAlbumFileList(entries, storage, 0);
result = TranslateResult(result);
entries.resize(std::min(album_entry_size, entries.size()));
if (!entries.empty()) {
ctx.WriteBuffer(entries);
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(entries.size());
}
void IAlbumAccessorService::DeleteAlbumFile(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto file_id{rp.PopRaw<AlbumFileId>()};

View File

@ -19,6 +19,7 @@ public:
~IAlbumAccessorService() override;
private:
void GetAlbumFileList(HLERequestContext& ctx);
void DeleteAlbumFile(HLERequestContext& ctx);
void IsAlbumMounted(HLERequestContext& ctx);
void Unknown18(HLERequestContext& ctx);

View File

@ -5,6 +5,7 @@
#include "core/hle/service/erpt/erpt.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
@ -15,7 +16,7 @@ public:
explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "SubmitContext"},
{0, &ErrorReportContext::SubmitContext, "SubmitContext"},
{1, nullptr, "CreateReportV0"},
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
@ -36,6 +37,14 @@ public:
RegisterHandlers(functions);
}
private:
void SubmitContext(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {

View File

@ -42,13 +42,13 @@ public:
{10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
{10702, nullptr, "AddPlayHistory"},
{11000, nullptr, "GetProfileImageUrl"},
{20100, nullptr, "GetFriendCount"},
{20101, nullptr, "GetNewlyFriendCount"},
{20100, &IFriendService::GetFriendCount, "GetFriendCount"},
{20101, &IFriendService::GetNewlyFriendCount, "GetNewlyFriendCount"},
{20102, nullptr, "GetFriendDetailedInfo"},
{20103, nullptr, "SyncFriendList"},
{20104, nullptr, "RequestSyncFriendList"},
{20110, nullptr, "LoadFriendSetting"},
{20200, nullptr, "GetReceivedFriendRequestCount"},
{20200, &IFriendService::GetReceivedFriendRequestCount, "GetReceivedFriendRequestCount"},
{20201, nullptr, "GetFriendRequestList"},
{20300, nullptr, "GetFriendCandidateList"},
{20301, nullptr, "GetNintendoNetworkIdInfo"},
@ -61,14 +61,14 @@ public:
{20501, nullptr, "GetRelationship"},
{20600, nullptr, "GetUserPresenceView"},
{20700, nullptr, "GetPlayHistoryList"},
{20701, nullptr, "GetPlayHistoryStatistics"},
{20701, &IFriendService::GetPlayHistoryStatistics, "GetPlayHistoryStatistics"},
{20800, nullptr, "LoadUserSetting"},
{20801, nullptr, "SyncUserSetting"},
{20900, nullptr, "RequestListSummaryOverlayNotification"},
{21000, nullptr, "GetExternalApplicationCatalog"},
{22000, nullptr, "GetReceivedFriendInvitationList"},
{22001, nullptr, "GetReceivedFriendInvitationDetailedInfo"},
{22010, nullptr, "GetReceivedFriendInvitationCountCache"},
{22010, &IFriendService::GetReceivedFriendInvitationCountCache, "GetReceivedFriendInvitationCountCache"},
{30100, nullptr, "DropFriendNewlyFlags"},
{30101, nullptr, "DeleteFriend"},
{30110, nullptr, "DropFriendNewlyFlag"},
@ -179,6 +179,30 @@ private:
rb.Push(ResultSuccess);
}
void GetFriendCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_Friend, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void GetNewlyFriendCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_Friend, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void GetReceivedFriendRequestCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_Friend, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void GetFriendList(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto friend_offset = rp.Pop<u32>();
@ -217,6 +241,21 @@ private:
rb.Push(true);
}
void GetPlayHistoryStatistics(HLERequestContext& ctx) {
LOG_ERROR(Service_Friend, "(STUBBED) called, check in out");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetReceivedFriendInvitationCountCache(HLERequestContext& ctx) {
LOG_DEBUG(Service_Friend, "(STUBBED) called, check in out");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* completion_event;

View File

@ -30,6 +30,7 @@ void LoopProcess(Core::System& system) {
// Notification Services for application
server_manager->RegisterNamedService("notif:a", std::make_shared<NOTIF_A>(system));
server_manager->RegisterNamedService("notif:s", std::make_shared<NOTIF_S>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -37,7 +37,13 @@ Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64
const auto iter = entries.find(title_id);
if (iter == entries.end()) {
return Glue::ResultProcessIdNotRegistered;
if (entries.empty()) {
return Glue::ResultProcessIdNotRegistered;
}
*out_control_property = entries.begin()->second.control;
return ResultSuccess;
}
*out_control_property = iter->second.control;

View File

@ -8,6 +8,7 @@
#include "common/logging/log.h"
#include "core/hle/service/glue/notif.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::Glue {
@ -156,4 +157,210 @@ std::vector<NOTIF_A::AlarmSetting>::iterator NOTIF_A::GetAlarmFromId(
});
}
class INotificationSystemEventAccessor final
: public ServiceFramework<INotificationSystemEventAccessor> {
public:
explicit INotificationSystemEventAccessor(Core::System& system_)
: ServiceFramework{system_, "INotificationSystemEventAccessor"}, service_context{
system_,
"IBtmSystemCore"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &INotificationSystemEventAccessor::Unknown0, "Unknown0"},
};
// clang-format on
RegisterHandlers(functions);
radio_event = service_context.CreateEvent("INotificationSystemEventAccessor::RadioEvent");
}
private:
void Unknown0(HLERequestContext& ctx) {
LOG_WARNING(Service_NOTIF, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(radio_event->GetReadableEvent());
}
Kernel::KEvent* radio_event;
KernelHelpers::ServiceContext service_context;
};
NOTIF_S::NOTIF_S(Core::System& system_) : ServiceFramework{system_, "notif:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{500, &NOTIF_S::RegisterAlarmSetting, "RegisterAlarmSetting"},
{510, &NOTIF_S::UpdateAlarmSetting, "UpdateAlarmSetting"},
{520, &NOTIF_S::ListAlarmSettings, "ListAlarmSettings"},
{530, &NOTIF_S::LoadApplicationParameter, "LoadApplicationParameter"},
{540, &NOTIF_S::DeleteAlarmSetting, "DeleteAlarmSetting"},
{1000, &NOTIF_S::Initialize, "Initialize"},
{1010, nullptr, "ListNotifications"},
{1020, nullptr, "DeleteNotification"},
{1030, nullptr, "ClearNotifications"},
{1040, &NOTIF_S::OpenNotificationSystemEventAccessor, "OpenNotificationSystemEventAccessor"},
{1500, nullptr, "SetPresentationSetting"},
{1510, &NOTIF_S::GetPresentationSetting, "GetPresentationSetting"},
{2000, nullptr, "GetAlarmSetting"},
{2001, nullptr, "Unknown2001"},
{2010, nullptr, "MuteAlarmSetting"},
{2020, nullptr, "IsAlarmSettingReady"},
{8000, nullptr, "Unknown8000"},
{8010, nullptr, "Unknown8010"},
{8999, nullptr, "Unknown8999"},
{9000, nullptr, "GetNextAlarm"},
};
// clang-format on
RegisterHandlers(functions);
}
NOTIF_S::~NOTIF_S() = default;
void NOTIF_S::RegisterAlarmSetting(HLERequestContext& ctx) {
const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
const auto application_parameter_size = ctx.GetReadBufferSize(1);
ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
"alarm_setting_buffer_size is not 0x40 bytes");
ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
"application_parameter_size is bigger than 0x400 bytes");
AlarmSetting new_alarm{};
memcpy(&new_alarm, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
// TODO: Count alarms per game id
if (alarms.size() >= max_alarms) {
LOG_ERROR(Service_NOTIF, "Alarm limit reached");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
}
new_alarm.alarm_setting_id = last_alarm_setting_id++;
alarms.push_back(new_alarm);
// TODO: Save application parameter data
LOG_WARNING(Service_NOTIF,
"(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
application_parameter_size, new_alarm.alarm_setting_id, new_alarm.kind,
new_alarm.muted);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(new_alarm.alarm_setting_id);
}
void NOTIF_S::UpdateAlarmSetting(HLERequestContext& ctx) {
const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
const auto application_parameter_size = ctx.GetReadBufferSize(1);
ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
"alarm_setting_buffer_size is not 0x40 bytes");
ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
"application_parameter_size is bigger than 0x400 bytes");
AlarmSetting alarm_setting{};
memcpy(&alarm_setting, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
const auto alarm_it = GetAlarmFromId(alarm_setting.alarm_setting_id);
if (alarm_it != alarms.end()) {
LOG_DEBUG(Service_NOTIF, "Alarm updated");
*alarm_it = alarm_setting;
// TODO: Save application parameter data
}
LOG_WARNING(Service_NOTIF,
"(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
application_parameter_size, alarm_setting.alarm_setting_id, alarm_setting.kind,
alarm_setting.muted);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void NOTIF_S::ListAlarmSettings(HLERequestContext& ctx) {
LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size());
// TODO: Only return alarms of this game id
ctx.WriteBuffer(alarms);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(alarms.size()));
}
void NOTIF_S::LoadApplicationParameter(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
const auto alarm_it = GetAlarmFromId(alarm_setting_id);
if (alarm_it == alarms.end()) {
LOG_ERROR(Service_NOTIF, "Invalid alarm setting id={}", alarm_setting_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
}
// TODO: Read application parameter related to this setting id
ApplicationParameter application_parameter{};
LOG_WARNING(Service_NOTIF, "(STUBBED) called, alarm_setting_id={}", alarm_setting_id);
ctx.WriteBuffer(application_parameter);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(application_parameter.size()));
}
void NOTIF_S::DeleteAlarmSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
std::erase_if(alarms, [alarm_setting_id](const AlarmSetting& alarm) {
return alarm.alarm_setting_id == alarm_setting_id;
});
LOG_INFO(Service_NOTIF, "called, alarm_setting_id={}", alarm_setting_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void NOTIF_S::Initialize(HLERequestContext& ctx) {
// TODO: Load previous alarms from config
LOG_WARNING(Service_NOTIF, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
std::vector<NOTIF_S::AlarmSetting>::iterator NOTIF_S::GetAlarmFromId(
AlarmSettingId alarm_setting_id) {
return std::find_if(alarms.begin(), alarms.end(),
[alarm_setting_id](const AlarmSetting& alarm) {
return alarm.alarm_setting_id == alarm_setting_id;
});
}
void NOTIF_S::OpenNotificationSystemEventAccessor(HLERequestContext& ctx) {
LOG_ERROR(Service_NOTIF, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INotificationSystemEventAccessor>(system);
}
void NOTIF_S::GetPresentationSetting(HLERequestContext& ctx) {
LOG_INFO(Service_NOTIF, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
} // namespace Service::Glue

View File

@ -68,5 +68,59 @@ private:
std::vector<AlarmSetting> alarms{};
AlarmSettingId last_alarm_setting_id{};
};
class NOTIF_S final : public ServiceFramework<NOTIF_S> {
public:
explicit NOTIF_S(Core::System& system_);
~NOTIF_S() override;
private:
static constexpr std::size_t max_alarms = 8;
// This is nn::notification::AlarmSettingId
using AlarmSettingId = u16;
static_assert(sizeof(AlarmSettingId) == 0x2, "AlarmSettingId is an invalid size");
using ApplicationParameter = std::array<u8, 0x400>;
static_assert(sizeof(ApplicationParameter) == 0x400, "ApplicationParameter is an invalid size");
struct DailyAlarmSetting {
s8 hour;
s8 minute;
};
static_assert(sizeof(DailyAlarmSetting) == 0x2, "DailyAlarmSetting is an invalid size");
struct WeeklyScheduleAlarmSetting {
INSERT_PADDING_BYTES(0xA);
std::array<DailyAlarmSetting, 0x7> day_of_week;
};
static_assert(sizeof(WeeklyScheduleAlarmSetting) == 0x18,
"WeeklyScheduleAlarmSetting is an invalid size");
// This is nn::notification::AlarmSetting
struct AlarmSetting {
AlarmSettingId alarm_setting_id;
u8 kind;
u8 muted;
INSERT_PADDING_BYTES(0x4);
Common::UUID account_id;
u64 application_id;
INSERT_PADDING_BYTES(0x8);
WeeklyScheduleAlarmSetting schedule;
};
static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size");
void RegisterAlarmSetting(HLERequestContext& ctx);
void UpdateAlarmSetting(HLERequestContext& ctx);
void ListAlarmSettings(HLERequestContext& ctx);
void LoadApplicationParameter(HLERequestContext& ctx);
void DeleteAlarmSetting(HLERequestContext& ctx);
void Initialize(HLERequestContext& ctx);
void OpenNotificationSystemEventAccessor(HLERequestContext& ctx);
void GetPresentationSetting(HLERequestContext& ctx);
std::vector<AlarmSetting>::iterator GetAlarmFromId(AlarmSettingId alarm_setting_id);
std::vector<AlarmSetting> alarms{};
AlarmSettingId last_alarm_setting_id{};
};
} // namespace Service::Glue

View File

@ -18,8 +18,8 @@ public:
explicit LBL(Core::System& system_) : ServiceFramework{system_, "lbl"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "SaveCurrentSetting"},
{1, nullptr, "LoadCurrentSetting"},
{0, &LBL::SaveCurrentSetting, "SaveCurrentSetting"},
{1, &LBL::LoadCurrentSetting, "LoadCurrentSetting"},
{2, &LBL::SetCurrentBrightnessSetting, "SetCurrentBrightnessSetting"},
{3, &LBL::GetCurrentBrightnessSetting, "GetCurrentBrightnessSetting"},
{4, nullptr, "ApplyCurrentBrightnessSettingToBacklight"},
@ -47,7 +47,7 @@ public:
{26, &LBL::EnableVrMode, "EnableVrMode"},
{27, &LBL::DisableVrMode, "DisableVrMode"},
{28, &LBL::IsVrModeEnabled, "IsVrModeEnabled"},
{29, nullptr, "IsAutoBrightnessControlSupported"},
{29, &LBL::IsAutoBrightnessControlSupported, "IsAutoBrightnessControlSupported"},
};
// clang-format on
@ -60,6 +60,20 @@ private:
On = 1,
};
void SaveCurrentSetting(HLERequestContext& ctx) {
LOG_WARNING(Service_LBL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void LoadCurrentSetting(HLERequestContext& ctx) {
LOG_WARNING(Service_LBL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SetCurrentBrightnessSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto brightness = rp.Pop<float>();
@ -310,6 +324,14 @@ private:
rb.Push(vr_mode_enabled);
}
void IsAutoBrightnessControlSupported(HLERequestContext& ctx) {
LOG_DEBUG(Service_LBL, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(auto_brightness_supported);
}
bool vr_mode_enabled = false;
float current_brightness = 1.0f;
float ambient_light_value = 0.0f;
@ -318,6 +340,7 @@ private:
bool backlight_enabled = true;
bool update_instantly = false;
bool auto_brightness = false; // TODO(ogniK): Move to system settings
bool auto_brightness_supported = true;
};
void LoopProcess(Core::System& system) {

View File

@ -39,7 +39,7 @@ public:
private:
void GetStateForMonitor(HLERequestContext& ctx) {
LOG_INFO(Service_LDN, "called");
LOG_DEBUG(Service_LDN, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@ -784,7 +784,7 @@ private:
}
void GetGroupInfo(HLERequestContext& ctx) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
LOG_DEBUG(Service_LDN, "(STUBBED) called");
struct GroupInfo {
std::array<u8, 0x200> info;

View File

@ -57,7 +57,7 @@ public:
{1, &NfcInterface::Finalize, "FinalizeOld"},
{2, &NfcInterface::GetState, "GetStateOld"},
{3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"},
{100, nullptr, "SetNfcEnabledOld"},
{100, &NfcInterface::SetNfcEnabled, "SetNfcEnabledOld"},
{400, &NfcInterface::Initialize, "Initialize"},
{401, &NfcInterface::Finalize, "Finalize"},
{402, &NfcInterface::GetState, "GetState"},
@ -71,7 +71,7 @@ public:
{410, &NfcInterface::GetTagInfo, "GetTagInfo"},
{411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"},
{412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"},
{500, nullptr, "SetNfcEnabled"},
{500, &NfcInterface::SetNfcEnabled, "SetNfcEnabled"},
{510, nullptr, "OutputTestWave"},
{1000, &NfcInterface::ReadMifare, "ReadMifare"},
{1001, &NfcInterface::WriteMifare, "WriteMifare"},

View File

@ -66,12 +66,9 @@ void NfcInterface::GetState(HLERequestContext& ctx) {
void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "called");
// TODO: This calls nn::settings::detail::GetNfcEnableFlag
const bool is_enabled = true;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(is_enabled);
rb.Push(true);
}
void NfcInterface::ListDevices(HLERequestContext& ctx) {
@ -213,6 +210,15 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
rb.PushCopyObjects(out_event);
}
void NfcInterface::SetNfcEnabled(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_enabled{rp.Pop<bool>()};
LOG_DEBUG(Service_NFC, "called, is_enabled={}", is_enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void NfcInterface::ReadMifare(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto device_handle{rp.Pop<u64>()};

View File

@ -28,6 +28,7 @@ public:
void GetTagInfo(HLERequestContext& ctx);
void AttachActivateEvent(HLERequestContext& ctx);
void AttachDeactivateEvent(HLERequestContext& ctx);
void SetNfcEnabled(HLERequestContext& ctx);
void ReadMifare(HLERequestContext& ctx);
void WriteMifare(HLERequestContext& ctx);
void SendCommandByPassThrough(HLERequestContext& ctx);

View File

@ -496,16 +496,27 @@ void IGeneralService::GetCurrentIpConfigInfo(HLERequestContext& ctx) {
rb.PushRaw<IpConfigInfo>(ip_config_info);
}
void IGeneralService::SetWirelessCommunicationEnabled(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_enabled{rp.Pop<bool>()};
LOG_DEBUG(Service_NIFM, "called, is_enabled={}", is_enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IGeneralService::IsWirelessCommunicationEnabled(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
const auto is_enabled = false;
LOG_DEBUG(Service_NIFM, "called, is_enabled={}", is_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(1);
rb.Push<u8>(is_enabled);
}
void IGeneralService::GetInternetConnectionStatus(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
LOG_DEBUG(Service_NIFM, "(STUBBED) called");
struct Output {
u8 type{static_cast<u8>(NetworkInterfaceType::WiFi_Ieee80211)};
@ -573,7 +584,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{13, nullptr, "GetCurrentAccessPointOld"},
{14, &IGeneralService::CreateTemporaryNetworkProfile, "CreateTemporaryNetworkProfile"},
{15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
{16, nullptr, "SetWirelessCommunicationEnabled"},
{16, &IGeneralService::SetWirelessCommunicationEnabled, "SetWirelessCommunicationEnabled"},
{17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
{18, &IGeneralService::GetInternetConnectionStatus, "GetInternetConnectionStatus"},
{19, nullptr, "SetEthernetCommunicationEnabled"},

View File

@ -31,6 +31,7 @@ private:
void GetCurrentIpAddress(HLERequestContext& ctx);
void CreateTemporaryNetworkProfile(HLERequestContext& ctx);
void GetCurrentIpConfigInfo(HLERequestContext& ctx);
void SetWirelessCommunicationEnabled(HLERequestContext& ctx);
void IsWirelessCommunicationEnabled(HLERequestContext& ctx);
void GetInternetConnectionStatus(HLERequestContext& ctx);
void IsEthernetCommunicationEnabled(HLERequestContext& ctx);

View File

@ -6,19 +6,23 @@
#include "core/hle/service/npns/npns.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::NPNS {
class NPNS_S final : public ServiceFramework<NPNS_S> {
public:
explicit NPNS_S(Core::System& system_) : ServiceFramework{system_, "npns:s"} {
explicit NPNS_S(Core::System& system_)
: ServiceFramework{system_, "npns:s"}, service_context{system, "npns:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{1, nullptr, "ListenAll"},
{2, nullptr, "ListenTo"},
{2, &NPNS_S::ListenTo, "ListenTo"},
{3, nullptr, "Receive"},
{4, nullptr, "ReceiveRaw"},
{5, nullptr, "GetReceiveEvent"},
{5, &NPNS_S::GetReceiveEvent, "GetReceiveEvent"},
{6, nullptr, "ListenUndelivered"},
{7, nullptr, "GetStateChangeEVent"},
{11, nullptr, "SubscribeTopic"},
@ -59,7 +63,30 @@ public:
// clang-format on
RegisterHandlers(functions);
get_recieve_event = service_context.CreateEvent("npns:s:GetReceiveEvent");
}
private:
void ListenTo(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto progam_id = rp.Pop<u64>();
LOG_WARNING(Service_AM, "(STUBBED) called, progam_id={}", progam_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetReceiveEvent(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(get_recieve_event->GetReadableEvent());
}
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* get_recieve_event;
};
class NPNS_U final : public ServiceFramework<NPNS_U> {

View File

@ -10,6 +10,7 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/ns/errors.h"
#include "core/hle/service/ns/iplatform_service_manager.h"
#include "core/hle/service/ns/language.h"
@ -34,12 +35,13 @@ IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
IAccountProxyInterface::~IAccountProxyInterface() = default;
IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
: ServiceFramework{system_, "IApplicationManagerInterface"} {
: ServiceFramework{system_, "IApplicationManagerInterface"},
service_context{system_, "IApplicationManagerInterface"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "ListApplicationRecord"},
{0, &IApplicationManagerInterface::ListApplicationRecord, "ListApplicationRecord"},
{1, nullptr, "GenerateApplicationRecordCount"},
{2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
{2, &IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent, "GetApplicationRecordUpdateSystemEvent"},
{3, nullptr, "GetApplicationViewDeprecated"},
{4, nullptr, "DeleteApplicationEntity"},
{5, nullptr, "DeleteApplicationCompletely"},
@ -68,14 +70,14 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{40, nullptr, "GetApplicationLogoData"},
{41, nullptr, "CalculateApplicationDownloadRequiredSize"},
{42, nullptr, "CleanupSdCard"},
{43, nullptr, "CheckSdCardMountStatus"},
{44, nullptr, "GetSdCardMountStatusChangedEvent"},
{43, &IApplicationManagerInterface::CheckSdCardMountStatus, "CheckSdCardMountStatus"},
{44, &IApplicationManagerInterface::GetSdCardMountStatusChangedEvent, "GetSdCardMountStatusChangedEvent"},
{45, nullptr, "GetGameCardAttachmentEvent"},
{46, nullptr, "GetGameCardAttachmentInfo"},
{47, nullptr, "GetTotalSpaceSize"},
{48, nullptr, "GetFreeSpaceSize"},
{48, &IApplicationManagerInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
{49, nullptr, "GetSdCardRemovedEvent"},
{52, nullptr, "GetGameCardUpdateDetectionEvent"},
{52, &IApplicationManagerInterface::GetGameCardUpdateDetectionEvent, "GetGameCardUpdateDetectionEvent"},
{53, nullptr, "DisableApplicationAutoDelete"},
{54, nullptr, "EnableApplicationAutoDelete"},
{55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"},
@ -93,7 +95,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{67, nullptr, "CancelApplicationApplyDelta"},
{68, nullptr, "ResumeApplicationApplyDelta"},
{69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
{70, nullptr, "ResumeAll"},
{70, &IApplicationManagerInterface::ResumeAll, "ResumeAll"},
{71, nullptr, "GetStorageSize"},
{80, nullptr, "RequestDownloadApplication"},
{81, nullptr, "RequestDownloadAddOnContent"},
@ -146,7 +148,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{502, nullptr, "RequestCheckGameCardRegistration"},
{503, nullptr, "RequestGameCardRegistrationGoldPoint"},
{504, nullptr, "RequestRegisterGameCard"},
{505, nullptr, "GetGameCardMountFailureEvent"},
{505, &IApplicationManagerInterface::GetGameCardMountFailureEvent, "GetGameCardMountFailureEvent"},
{506, nullptr, "IsGameCardInserted"},
{507, nullptr, "EnsureGameCardAccess"},
{508, nullptr, "GetLastGameCardMountFailureResult"},
@ -220,10 +222,10 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
{1701, nullptr, "GetApplicationView"},
{1701, &IApplicationManagerInterface::GetApplicationView, "GetApplicationView"},
{1702, nullptr, "GetApplicationDownloadTaskStatus"},
{1703, nullptr, "GetApplicationViewDownloadErrorContext"},
{1704, nullptr, "GetApplicationViewWithPromotionInfo"},
{1704, &IApplicationManagerInterface::GetApplicationViewWithPromotionInfo, "GetApplicationViewWithPromotionInfo"},
{1705, nullptr, "IsPatchAutoDeletableApplication"},
{1800, nullptr, "IsNotificationSetupCompleted"},
{1801, nullptr, "GetLastNotificationInfoCount"},
@ -326,19 +328,97 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
// clang-format on
RegisterHandlers(functions);
record_update_system_event =
service_context.CreateEvent("IApplicationManagerInterface::RecordUpdateSystemEvent");
gamecard_update_detection_event =
service_context.CreateEvent("IApplicationManagerInterface::GamecardUpdateDetectionEvent");
gamecard_mount_status_event =
service_context.CreateEvent("IApplicationManagerInterface::GamecardMountStatusEvent");
gamecard_mount_failure_event =
service_context.CreateEvent("IApplicationManagerInterface::GamecardMountFailureEvent");
}
IApplicationManagerInterface::~IApplicationManagerInterface() = default;
IApplicationManagerInterface::~IApplicationManagerInterface(){
service_context.CloseEvent(record_update_system_event);
service_context.CloseEvent(gamecard_update_detection_event);
service_context.CloseEvent(gamecard_mount_status_event);
service_context.CloseEvent(gamecard_mount_failure_event);
};
void IApplicationManagerInterface::ListApplicationRecord(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto offset = rp.Pop<s32>();
const auto limit = ctx.GetWriteBufferNumElements<ApplicationRecord>();
LOG_ERROR(Service_NS, "(STUBBED) called");
std::vector<ApplicationRecord> application_records;
std::vector<ApplicationRecord> application_records2;
application_records.push_back(ApplicationRecord{
.application_id = 0x010074F013262000,
.type = 3,
.unknown = 2,
.unknown2 = 0,
});
application_records.push_back(ApplicationRecord{
.application_id = 0x01000F0002BB6000,
.type = 2,
.unknown = 2,
.unknown2 = 1,
});
application_records.push_back(ApplicationRecord{
.application_id = 0x0100A7F002830000,
.type = 1,
.unknown = 2,
.unknown2 = 2,
});
application_records.push_back(ApplicationRecord{
.application_id = 0x01008DF012A7A000,
.type = 3,
.unknown = 2,
.unknown2 = 3,
});
for (const auto& data : application_records) {
if (application_records2.size() >= limit) {
break;
}
if (offset > 0) {
offset--;
continue;
}
application_records2.push_back(data);
}
if (!application_records2.empty()) {
ctx.WriteBuffer(application_records2);
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(application_records2.size());
}
void IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
record_update_system_event->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(record_update_system_event->GetReadableEvent());
}
void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto flag = rp.PopRaw<u64>();
LOG_DEBUG(Service_NS, "called with flag={:016X}", flag);
const auto title_id = rp.PopRaw<u64>();
const auto size = ctx.GetWriteBufferSize();
LOG_ERROR(Service_NS, "called with flag={:016X}, title_id={:016X}", flag, title_id);
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
const auto control = pm.GetControlMetadata();
@ -389,6 +469,89 @@ void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext&
rb.Push<u32>(static_cast<u32>(out.size()));
}
void IApplicationManagerInterface::GetGameCardMountFailureEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(gamecard_mount_failure_event->GetReadableEvent());
}
void IApplicationManagerInterface::GetApplicationView(HLERequestContext& ctx) {
std::vector<u64> application_id(ctx.GetReadBufferNumElements<u64>());
const auto app_buffer = ctx.ReadBuffer();
memcpy(application_id.data(), app_buffer.data(), app_buffer.size());
std::vector<ApplicationView> app_view;
LOG_DEBUG(Service_NS, "(STUBBED) called, size={}", application_id.size());
for (const u64& data : application_id) {
app_view.push_back(ApplicationView{
.application_id = data,
});
}
ctx.WriteBuffer(app_view);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(HLERequestContext& ctx) {
std::vector<u64> application_id(ctx.GetReadBufferNumElements<u64>());
const auto app_buffer = ctx.ReadBuffer();
memcpy(application_id.data(), app_buffer.data(), app_buffer.size());
std::vector<ApplicationViewWithPromotionInfo> app_view;
LOG_DEBUG(Service_NS, "(STUBBED) called, size={}", application_id.size());
for (const u64& data : application_id) {
app_view.push_back(ApplicationViewWithPromotionInfo{
.view{
.application_id = data,
},
.promotion = {},
});
}
ctx.WriteBuffer(app_view);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IApplicationManagerInterface::CheckSdCardMountStatus(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IApplicationManagerInterface::GetSdCardMountStatusChangedEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(gamecard_mount_status_event->GetReadableEvent());
}
void IApplicationManagerInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(1024UL * 1024UL * 1024UL);
}
void IApplicationManagerInterface::GetGameCardUpdateDetectionEvent(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(gamecard_update_detection_event->GetReadableEvent());
}
void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto supported_languages = rp.Pop<u32>();
@ -407,7 +570,7 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
const u32 supported_languages) {
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
LOG_ERROR(Service_NS, "called with supported_languages={:08X}", supported_languages);
// Get language code from settings
const auto language_code =
@ -459,6 +622,13 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
}
}
void IApplicationManagerInterface::ResumeAll(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
u64* out_language_code, u8 application_language) {
const auto language_code =
@ -502,7 +672,7 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
// clang-format off
static const FunctionInfo functions[] = {
{11, nullptr, "CalculateApplicationOccupiedSize"},
{43, nullptr, "CheckSdCardMountStatus"},
{43, &IContentManagementInterface::CheckSdCardMountStatus, "CheckSdCardMountStatus"},
{47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
{48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
{600, nullptr, "CountApplicationContentMeta"},
@ -517,24 +687,31 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
IContentManagementInterface::~IContentManagementInterface() = default;
void IContentManagementInterface::CheckSdCardMountStatus(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage{rp.PopEnum<FileSys::StorageId>()};
IPC::RequestParser rp{ ctx };
const auto storage{ rp.PopEnum<FileSys::StorageId>() };
LOG_INFO(Service_Capture, "called, storage={}", storage);
IPC::ResponseBuilder rb{ctx, 4};
IPC::ResponseBuilder rb{ ctx, 4 };
rb.Push(ResultSuccess);
rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
}
void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto storage{rp.PopEnum<FileSys::StorageId>()};
IPC::RequestParser rp{ ctx };
const auto storage{ rp.PopEnum<FileSys::StorageId>() };
LOG_INFO(Service_Capture, "called, storage={}", storage);
IPC::ResponseBuilder rb{ctx, 4};
IPC::ResponseBuilder rb{ ctx, 4 };
rb.Push(ResultSuccess);
rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
}
@ -564,7 +741,7 @@ IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
{704, nullptr, "ListDownloadTaskStatus"},
{705, nullptr, "RequestDownloadTaskListData"},
{706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
{707, nullptr, "EnableAutoCommit"},
{707, &IDownloadTaskInterface::EnableAutoCommit, "EnableAutoCommit"},
{708, nullptr, "DisableAutoCommit"},
{709, nullptr, "TriggerDynamicCommitEvent"},
};
@ -575,6 +752,12 @@ IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
IDownloadTaskInterface::~IDownloadTaskInterface() = default;
void IDownloadTaskInterface::EnableAutoCommit(HLERequestContext& ctx) {
LOG_ERROR(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
IECommerceInterface::IECommerceInterface(Core::System& system_)
: ServiceFramework{system_, "IECommerceInterface"} {
// clang-format off
@ -753,17 +936,18 @@ public:
class NS_SU final : public ServiceFramework<NS_SU> {
public:
explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} {
explicit NS_SU(Core::System& system_)
: ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetBackgroundNetworkUpdateState"},
{0, &NS_SU::GetBackgroundNetworkUpdateState, "GetBackgroundNetworkUpdateState"},
{1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
{2, nullptr, "NotifyExFatDriverRequired"},
{3, nullptr, "ClearExFatDriverStatusForDebug"},
{4, nullptr, "RequestBackgroundNetworkUpdate"},
{5, nullptr, "NotifyBackgroundNetworkUpdate"},
{6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
{9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
{9, &NS_SU::GetSystemUpdateNotificationEventForContentDelivery, "GetSystemUpdateNotificationEventForContentDelivery"},
{10, nullptr, "NotifySystemUpdateForContentDelivery"},
{11, nullptr, "PrepareShutdown"},
{12, nullptr, "Unknown12"},
@ -777,16 +961,43 @@ public:
// clang-format on
RegisterHandlers(functions);
update_notification_event = service_context.CreateEvent("NS_SU::UpdateNotificationEvent");
}
private:
Kernel::KEvent* update_notification_event;
KernelHelpers::ServiceContext service_context;
enum class BackgroundNetworkUpdateState {
None,
InProgress,
Ready,
};
void GetBackgroundNetworkUpdateState(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(BackgroundNetworkUpdateState::None);
}
void OpenSystemUpdateControl(HLERequestContext& ctx) {
LOG_DEBUG(Service_NS, "called");
LOG_ERROR(Service_NS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISystemUpdateControl>(system);
}
void GetSystemUpdateNotificationEventForContentDelivery(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(update_notification_event->GetReadableEvent());
}
};
class NS_VM final : public ServiceFramework<NS_VM> {
@ -813,6 +1024,27 @@ private:
}
};
class ISenderService final : public ServiceFramework<ISenderService> {
public:
explicit ISenderService(Core::System& system_) : ServiceFramework{system_, "ovln:snd"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ISenderService::OpenSender, "OpenSender"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenSender(HLERequestContext& ctx) {
LOG_ERROR(Service_NS, "(STUBBED) called, check in out");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
@ -832,6 +1064,9 @@ void LoopProcess(Core::System& system) {
std::make_shared<IPlatformServiceManager>(system, "pl:s"));
server_manager->RegisterNamedService("pl:u",
std::make_shared<IPlatformServiceManager>(system, "pl:u"));
server_manager->RegisterNamedService("ovln:snd", std::make_shared<ISenderService>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Core {
@ -33,9 +34,68 @@ public:
u8 application_language);
private:
struct ApplicationRecord {
u64 application_id;
u8 type;
u8 unknown;
INSERT_PADDING_BYTES(0x6);
u8 unknown2;
INSERT_PADDING_BYTES(0x7);
};
/// ApplicationView
struct ApplicationView {
u64 application_id; ///< ApplicationId.
u8 unk_x8[0x4]; ///< Unknown.
u32 flags; ///< Flags.
u8 unk_x10[0x10]; ///< Unknown.
u32 unk_x20; ///< Unknown.
u16 unk_x24; ///< Unknown.
u8 unk_x26[0x2]; ///< Unknown.
u8 unk_x28[0x8]; ///< Unknown.
u8 unk_x30[0x10]; ///< Unknown.
u32 unk_x40; ///< Unknown.
u8 unk_x44; ///< Unknown.
u8 unk_x45[0xb]; ///< Unknown.
};
/// NsPromotionInfo
struct PromotionInfo {
u64 start_timestamp; ///< POSIX timestamp for the promotion start.
u64 end_timestamp; ///< POSIX timestamp for the promotion end.
s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds
///< ({end_timestamp - current_time} converted to nanoseconds).
INSERT_PADDING_BYTES(0x4);
u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear:
///< remaining_time is set.
INSERT_PADDING_BYTES(0x3);
};
/// NsApplicationViewWithPromotionInfo
struct ApplicationViewWithPromotionInfo {
ApplicationView view; ///< \ref NsApplicationView
PromotionInfo promotion; ///< \ref NsPromotionInfo
};
void ListApplicationRecord(HLERequestContext& ctx);
void GetApplicationRecordUpdateSystemEvent(HLERequestContext& ctx);
void GetApplicationControlData(HLERequestContext& ctx);
void GetGameCardMountFailureEvent(HLERequestContext& ctx);
void GetApplicationView(HLERequestContext& ctx);
void GetApplicationViewWithPromotionInfo(HLERequestContext& ctx);
void CheckSdCardMountStatus(HLERequestContext& ctx);
void GetSdCardMountStatusChangedEvent(HLERequestContext& ctx);
void GetFreeSpaceSize(HLERequestContext& ctx);
void GetGameCardUpdateDetectionEvent(HLERequestContext& ctx);
void GetApplicationDesiredLanguage(HLERequestContext& ctx);
void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
void ResumeAll(HLERequestContext& ctx);
Kernel::KEvent* record_update_system_event;
Kernel::KEvent* gamecard_update_detection_event;
Kernel::KEvent* gamecard_mount_status_event;
Kernel::KEvent* gamecard_mount_failure_event;
KernelHelpers::ServiceContext service_context;
};
class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
@ -50,6 +110,7 @@ public:
~IContentManagementInterface() override;
private:
void CheckSdCardMountStatus(HLERequestContext& ctx);
void GetTotalSpaceSize(HLERequestContext& ctx);
void GetFreeSpaceSize(HLERequestContext& ctx);
};
@ -64,6 +125,9 @@ class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterf
public:
explicit IDownloadTaskInterface(Core::System& system_);
~IDownloadTaskInterface() override;
private:
void EnableAutoCommit(HLERequestContext& ctx);
};
class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {

View File

@ -79,12 +79,20 @@ public:
: ServiceFramework{system_, "INativeHandleHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetNativeHandle"},
{0, &INativeHandleHolder::GetNativeHandle, "GetNativeHandle"},
};
// clang-format on
RegisterHandlers(functions);
}
void GetNativeHandle(HLERequestContext& ctx) {
LOG_ERROR(Service_OLSC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
};
class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
@ -198,6 +206,7 @@ public:
{1122, nullptr, "RepairIssue2"},
{1123, nullptr, "RepairIssue3"},
{1124, nullptr, "Unknown1124"},
{10000, &IOlscServiceForSystemService::Unknown10000, "Unknown10000"},
};
// clang-format on
@ -212,6 +221,14 @@ private:
rb.Push(ResultSuccess);
rb.PushIpcInterface<ITransferTaskListController>(system);
}
void Unknown10000(HLERequestContext& ctx) {
LOG_INFO(Service_OLSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IOlscServiceForSystemService>(system);
}
};
void LoopProcess(Core::System& system) {

View File

@ -39,7 +39,7 @@ public:
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
{1008, nullptr, "EnterRestrictedSystemSettings"},
{1009, nullptr, "LeaveRestrictedSystemSettings"},
{1010, nullptr, "IsRestrictedSystemSettingsEntered"},
{1010, &IParentalControlService::IsRestrictedSystemSettingsEntered, "IsRestrictedSystemSettingsEntered"},
{1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
{1012, nullptr, "GetRestrictedFeatures"},
{1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"},
@ -75,7 +75,7 @@ public:
{1203, nullptr, "SetPinCode"},
{1204, nullptr, "GenerateInquiryCode"},
{1205, nullptr, "CheckMasterKey"},
{1206, nullptr, "GetPinCodeLength"},
{1206, &IParentalControlService::GetPinCodeLength, "GetPinCodeLength"},
{1207, nullptr, "GetPinCodeChangedEvent"},
{1208, nullptr, "GetPinCode"},
{1403, &IParentalControlService::IsPairingActive, "IsPairingActive"},
@ -87,11 +87,11 @@ public:
{1426, nullptr, "GetPostEventInterval"},
{1427, nullptr, "SetPostEventInterval"},
{1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"},
{1451, nullptr, "StartPlayTimer"},
{1452, nullptr, "StopPlayTimer"},
{1453, nullptr, "IsPlayTimerEnabled"},
{1451, &IParentalControlService::StartPlayTimer, "StartPlayTimer"},
{1452, &IParentalControlService::StopPlayTimer, "StopPlayTimer"},
{1453, &IParentalControlService::IsPlayTimerEnabled, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"},
{1455, nullptr, "IsRestrictedByPlayTimer"},
{1455, &IParentalControlService::IsRestrictedByPlayTimer, "IsRestrictedByPlayTimer"},
{1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"},
{1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"},
{1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"},
@ -259,6 +259,16 @@ private:
rb.Push(ResultSuccess);
rb.Push<u8>(is_temporary_unlocked);
}
void IsRestrictedSystemSettingsEntered(HLERequestContext& ctx) {
const bool is_temporary_unlocked = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
is_temporary_unlocked);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_temporary_unlocked);
}
void ConfirmStereoVisionPermission(HLERequestContext& ctx) {
LOG_DEBUG(Service_PCTL, "called");
@ -360,6 +370,16 @@ private:
}
}
void GetPinCodeLength(HLERequestContext& ctx) {
const bool is_pairing_active = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void IsPairingActive(HLERequestContext& ctx) {
const bool is_pairing_active = false;
@ -378,6 +398,39 @@ private:
rb.PushCopyObjects(synchronization_event->GetReadableEvent());
}
void StartPlayTimer(HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void StopPlayTimer(HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IsPlayTimerEnabled(HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void IsRestrictedByPlayTimer(HLERequestContext& ctx) {
const bool is_temporary_unlocked = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
is_temporary_unlocked);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_temporary_unlocked);
}
void GetPlayTimerSettings(HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");

View File

@ -71,11 +71,51 @@ private:
}
};
class IReceiver final : public ServiceFramework<IReceiver> {
public:
explicit IReceiver(Core::System& system_) : ServiceFramework{system_, "IReceiver"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "AddSource"},
{1, nullptr, "RemoveSource"},
{2, nullptr, "GetReceiveEventHandle"},
{3, nullptr, "Receive"},
{4, nullptr, "ReceiveWithTick"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class OvlnRcv final : public ServiceFramework<OvlnRcv> {
public:
explicit OvlnRcv(Core::System& system_) : ServiceFramework{system_, "ovln:rcv"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &OvlnRcv::OpenReceiver, "OpenReceiver"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenReceiver(HLERequestContext& ctx) {
LOG_DEBUG(Service_PSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IReceiver>(system);
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("psc:c", std::make_shared<IPmControl>(system));
server_manager->RegisterNamedService("psc:m", std::make_shared<IPmService>(system));
server_manager->RegisterNamedService("ovln:rcv", std::make_shared<OvlnRcv>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -158,9 +158,11 @@ void ISettingsServer::GetKeyCodeMap2(HLERequestContext& ctx) {
void ISettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
ctx.WriteBuffer(Settings::values.device_name.GetValue());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
ctx.WriteBuffer(Settings::values.device_name.GetValue());
}
} // namespace Service::Set

View File

@ -305,6 +305,21 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
RegisterHandlers(functions);
SetupSettings();
Time::Clock::SteadyClockTimePoint timestamp{
.time_point = 1691079299,
.clock_source_id = Common::UUID::MakeRandom(),
};
EulaVersion eula_version{
.version = 65536,
.region_code = RegionCode::Usa,
.clock_type = EulaVersionClockType::SteadyClock,
.posix_time = 4575657222473777152,
.timestamp = timestamp,
};
m_system_settings.eula_versions[0] = eula_version;
m_system_settings.eula_version_count = 1;
m_save_thread =
std::jthread([this](std::stop_token stop_token) { StoreSettingsThreadFunc(stop_token); });
}
@ -529,6 +544,16 @@ void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto lock_screen_flag{rp.Pop<bool>()};
LOG_INFO(Service_SET, "called, lock_screen_flag={}", lock_screen_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetAccountSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called");
@ -915,6 +940,25 @@ void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
const auto nfc_enable_flag = true;
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", nfc_enable_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(nfc_enable_flag);
}
void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto nfc_enable_flag{rp.Pop<bool>()};
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", nfc_enable_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetSleepSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
m_system_settings.sleep_settings.flags.raw,
@ -961,6 +1005,27 @@ void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetWirelessLanEnableFlag(HLERequestContext& ctx) {
const auto wireless_lan_enable_flag = false;
LOG_WARNING(Service_SET, "(STUBBED) called, wireless_lan_enable_flag={}",
wireless_lan_enable_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(wireless_lan_enable_flag);
}
void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto wireless_lan_enable_flag{rp.Pop<bool>()};
LOG_DEBUG(Service_SET, "(STUBBED) called, wireless_lan_enable_flag={}",
wireless_lan_enable_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, flags={}, timestamp={}",
m_system_settings.initial_launch_settings_packed.flags.raw,

View File

@ -80,6 +80,8 @@ private:
void SetExternalSteadyClockSourceId(HLERequestContext& ctx);
void GetUserSystemClockContext(HLERequestContext& ctx);
void SetUserSystemClockContext(HLERequestContext& ctx);
void GetLockScreenFlag(HLERequestContext& ctx);
void SetLockScreenFlag(HLERequestContext& ctx);
void GetAccountSettings(HLERequestContext& ctx);
void SetAccountSettings(HLERequestContext& ctx);
void GetEulaVersions(HLERequestContext& ctx);

View File

@ -153,7 +153,7 @@ public:
{2400, nullptr, "OpenIndirectLayer"},
{2401, nullptr, "CloseIndirectLayer"},
{2402, nullptr, "FlipIndirectLayer"},
{3000, nullptr, "ListDisplayModes"},
{3000, &ISystemDisplayService::ListDisplayModes, "ListDisplayModes"},
{3001, nullptr, "ListDisplayRgbRanges"},
{3002, nullptr, "ListDisplayContentTypes"},
{3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"},
@ -319,6 +319,28 @@ private:
rb.Push(ResultSuccess);
}
void ListDisplayModes(HLERequestContext& ctx) {
struct DisplayInfo {
u8 unknownString[0x40];
bool unknownBool;
INSERT_PADDING_BYTES(0x7);
u64 unknownU64_1;
u64 unknownU64_2;
u64 unknownU64_3;
};
static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo is an invalid size");
LOG_WARNING(Service_VI, "(STUBBED) called");
std::vector<DisplayInfo> display_modes(1);
ctx.WriteBuffer(display_modes);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(1);
}
void GetDisplayMode(HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");

View File

@ -14,6 +14,7 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "core/core.h"
#include "core/hle/service/glue/glue_manager.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
@ -326,6 +327,21 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control);
if (control != nullptr) {
GetMetadataFromControlNCA(patch, *control, icon, name);
std::vector<u8> nacp_data;
FileSys::NACP nacp;
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
nacp_data = nacp.GetRawBytes();
} else {
nacp_data.resize(sizeof(FileSys::RawNACP));
}
Service::Glue::ApplicationLaunchProperty launch{};
launch.title_id = program_id;
launch.version = patch.GetGameVersion().value_or(0);
launch.base_game_storage_id = FileSys::StorageId::NandUser;
launch.update_storage_id = FileSys::StorageId::NandSystem;
system.GetARPManager().Register(launch.title_id, launch, std::move(nacp_data));
}
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,

View File

@ -1585,6 +1585,7 @@ void GMainWindow::ConnectMenuEvents() {
[this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); });
connect_menu(ui->action_Load_Cabinet_Formatter,
[this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
connect_menu(ui->action_Load_QLaunch, &GMainWindow::OnQlaunch);
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);
@ -1620,6 +1621,7 @@ void GMainWindow::UpdateMenuState() {
ui->action_Load_Cabinet_Restorer,
ui->action_Load_Cabinet_Formatter,
ui->action_Load_Mii_Edit,
ui->action_Load_QLaunch,
ui->action_Open_Controller_Menu};
for (QAction* action : running_actions) {
@ -4201,6 +4203,29 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
BootGame(filename, CabinetId);
}
void GMainWindow::OnQlaunch() {
constexpr u64 QlaunchId = static_cast<u64>(Service::AM::Applets::AppletProgramId::QLaunch);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QMessageBox::warning(this, tr("No firmware available"),
tr("Please install the firmware to use the Mii editor."));
return;
}
auto mii_applet_nca = bis_system->GetEntry(QlaunchId, FileSys::ContentRecordType::Program);
if (!mii_applet_nca) {
QMessageBox::warning(this, tr("Mii Edit Applet"),
tr("Mii editor is not available. Please reinstall firmware."));
return;
}
system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::QLaunch);
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, QlaunchId);
}
void GMainWindow::OnMiiEdit() {
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();

View File

@ -396,6 +396,7 @@ private slots:
void ResetWindowSize900();
void ResetWindowSize1080();
void OnAlbum();
void OnQlaunch();
void OnCabinet(Service::NFP::CabinetMode mode);
void OnMiiEdit();
void OnOpenControllerMenu();

View File

@ -159,6 +159,7 @@
<addaction name="action_Rederive"/>
<addaction name="action_Verify_installed_contents"/>
<addaction name="separator"/>
<addaction name="action_Load_QLaunch"/>
<addaction name="menu_cabinet_applet"/>
<addaction name="action_Load_Album"/>
<addaction name="action_Load_Mii_Edit"/>
@ -407,6 +408,11 @@
<string>&amp;Format Amiibo</string>
</property>
</action>
<action name="action_Load_QLaunch">
<property name="text">
<string>Open &amp;Home menu</string>
</property>
</action>
<action name="action_Load_Mii_Edit">
<property name="text">
<string>Open &amp;Mii Editor</string>