diff options
Diffstat (limited to 'src/core/hle/service')
23 files changed, 559 insertions, 65 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index c6437a671..8318eff5f 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -242,6 +242,28 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo LOG_DEBUG(Service_ACC, "called"); } +void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + // A u8 is passed into this function which we can safely ignore. It's to determine if we have + // access to use the network or not by the looks of it + IPC::ResponseBuilder rb{ctx, 6}; + if (profile_manager->GetUserCount() != 1) { + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u128>(INVALID_UUID); + return; + } + auto user_list = profile_manager->GetAllUsers(); + if (user_list.empty()) { + rb.Push(ResultCode(-1)); // TODO(ogniK): Find the correct error code + rb.PushRaw<u128>(INVALID_UUID); + return; + } + + // Select the first user we have + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u128>(profile_manager->GetUser(0)->uuid); +} + Module::Interface::Interface(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, const char* name) : ServiceFramework(name), module(std::move(module)), diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index c7ed74351..89b2104fa 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -27,6 +27,7 @@ public: void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); + void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); protected: std::shared_ptr<Module> module; diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index ad455c3a7..5e2030355 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp @@ -17,7 +17,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {5, &ACC_SU::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, - {51, nullptr, "TrySelectUserWithoutInteraction"}, + {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, nullptr, "GetUserRegistrationNotifier"}, {101, nullptr, "GetUserStateChangeNotifier"}, diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 72d4adf35..a4d705b45 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -17,7 +17,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {5, &ACC_U0::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, - {51, nullptr, "TrySelectUserWithoutInteraction"}, + {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index d480f08e5..8fffc93b5 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp @@ -17,7 +17,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {5, &ACC_U1::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, - {51, nullptr, "TrySelectUserWithoutInteraction"}, + {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, nullptr, "GetUserRegistrationNotifier"}, {101, nullptr, "GetUserStateChangeNotifier"}, diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ac3ff9f20..0477ce66e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -338,7 +338,54 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c LOG_WARNING(Service_AM, "(STUBBED) called"); } -ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { +AppletMessageQueue::AppletMessageQueue() { + auto& kernel = Core::System::GetInstance().Kernel(); + on_new_message = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, + "AMMessageQueue:OnMessageRecieved"); + on_operation_mode_changed = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "AMMessageQueue:OperationModeChanged"); +} + +AppletMessageQueue::~AppletMessageQueue() = default; + +const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetMesssageRecieveEvent() const { + return on_new_message; +} + +const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetOperationModeChangedEvent() const { + return on_operation_mode_changed; +} + +void AppletMessageQueue::PushMessage(AppletMessage msg) { + messages.push(msg); + on_new_message->Signal(); +} + +AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { + if (messages.empty()) { + on_new_message->Clear(); + return AppletMessage::NoMessage; + } + auto msg = messages.front(); + messages.pop(); + if (messages.empty()) { + on_new_message->Clear(); + } + return msg; +} + +std::size_t AppletMessageQueue::GetMessageCount() const { + return messages.size(); +} + +void AppletMessageQueue::OperationModeChanged() { + PushMessage(AppletMessage::OperationModeChanged); + PushMessage(AppletMessage::PerformanceModeChanged); + on_operation_mode_changed->Signal(); +} + +ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ICommonStateGetter"), msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, @@ -388,21 +435,19 @@ void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) { - event->Signal(); - IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); + rb.PushCopyObjects(msg_queue->GetMesssageRecieveEvent()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(15); + rb.PushEnum<AppletMessageQueue::AppletMessage>(msg_queue->PopMessage()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { @@ -414,13 +459,11 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) { - event->Signal(); - IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); + rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) { @@ -444,7 +487,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { @@ -454,7 +497,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked : APM::PerformanceMode::Handheld)); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { @@ -840,8 +883,12 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) { void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr<NVFlinger::NVFlinger> nvflinger) { - std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager); - std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager); + auto message_queue = std::make_shared<AppletMessageQueue>(); + message_queue->PushMessage( + AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on game boot + + std::make_shared<AppletAE>(nvflinger, message_queue)->InstallAsService(service_manager); + std::make_shared<AppletOE>(nvflinger, message_queue)->InstallAsService(service_manager); std::make_shared<IdleSys>()->InstallAsService(service_manager); std::make_shared<OMM>()->InstallAsService(service_manager); std::make_shared<SPSM>()->InstallAsService(service_manager); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 095f94851..2f1c20bce 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -5,6 +5,7 @@ #pragma once #include <memory> +#include <queue> #include "core/hle/service/service.h" namespace Kernel { @@ -39,6 +40,31 @@ enum SystemLanguage { TraditionalChinese = 16, }; +class AppletMessageQueue { +public: + enum class AppletMessage : u32 { + NoMessage = 0, + FocusStateChanged = 15, + OperationModeChanged = 30, + PerformanceModeChanged = 31, + }; + + AppletMessageQueue(); + ~AppletMessageQueue(); + + const Kernel::SharedPtr<Kernel::Event>& GetMesssageRecieveEvent() const; + const Kernel::SharedPtr<Kernel::Event>& GetOperationModeChangedEvent() const; + void PushMessage(AppletMessage msg); + AppletMessage PopMessage(); + std::size_t GetMessageCount() const; + void OperationModeChanged(); + +private: + std::queue<AppletMessage> messages; + Kernel::SharedPtr<Kernel::Event> on_new_message; + Kernel::SharedPtr<Kernel::Event> on_operation_mode_changed; +}; + class IWindowController final : public ServiceFramework<IWindowController> { public: IWindowController(); @@ -102,7 +128,7 @@ private: class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { public: - ICommonStateGetter(); + explicit ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue); ~ICommonStateGetter() override; private: @@ -126,6 +152,7 @@ private: void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); Kernel::SharedPtr<Kernel::Event> event; + std::shared_ptr<AppletMessageQueue> msg_queue; }; class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 68ea778e8..ec93e3529 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -12,8 +12,10 @@ namespace Service::AM { class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { public: - explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)) { + explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, @@ -32,7 +34,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -93,12 +95,15 @@ private: } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { public: - explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)) { + explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, @@ -119,7 +124,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -186,31 +191,34 @@ private: LOG_DEBUG(Service_AM, "called"); } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystemAppletProxy>(nvflinger); + rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); + rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); + rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } -AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)) { +AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, @@ -228,4 +236,8 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletAE::~AppletAE() = default; +const std::shared_ptr<AppletMessageQueue>& AppletAE::GetMessageQueue() const { + return msg_queue; +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 1ed77baa4..902db2665 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -17,15 +17,19 @@ namespace AM { class AppletAE final : public ServiceFramework<AppletAE> { public: - explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); + explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue); ~AppletAE() override; + const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; + private: void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx); void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; } // namespace AM diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index 60717afd9..20c8d5fff 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -12,8 +12,10 @@ namespace Service::AM { class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { public: - explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)) { + explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -70,7 +72,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -89,17 +91,20 @@ private: } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IApplicationProxy>(nvflinger); + rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } -AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)) { +AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, }; @@ -108,4 +113,8 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletOE::~AppletOE() = default; +const std::shared_ptr<AppletMessageQueue>& AppletOE::GetMessageQueue() const { + return msg_queue; +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 60cfdfd9d..bbd0108ef 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -17,13 +17,17 @@ namespace AM { class AppletOE final : public ServiceFramework<AppletOE> { public: - explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); + explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue); ~AppletOE() override; + const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; + private: void OpenApplicationProxy(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; } // namespace AM diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index fac6785a5..35a8bef6c 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -32,8 +32,8 @@ public: {5, &IAudioRenderer::Start, "Start"}, {6, &IAudioRenderer::Stop, "Stop"}, {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, - {8, nullptr, "SetRenderingTimeLimit"}, - {9, nullptr, "GetRenderingTimeLimit"}, + {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, + {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, {10, nullptr, "RequestUpdateAuto"}, {11, nullptr, "ExecuteAudioRendererRendering"}, }; @@ -110,8 +110,29 @@ private: LOG_WARNING(Service_Audio, "(STUBBED) called"); } + void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + rendering_time_limit_percent = rp.Pop<u32>(); + ASSERT(rendering_time_limit_percent >= 0 && rendering_time_limit_percent <= 100); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service_Audio, "called. rendering_time_limit_percent={}", + rendering_time_limit_percent); + } + + void GetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(rendering_time_limit_percent); + } + Kernel::SharedPtr<Kernel::Event> system_event; std::unique_ptr<AudioCore::AudioRenderer> renderer; + u32 rendering_time_limit_percent = 100; }; class IAudioDevice final : public ServiceFramework<IAudioDevice> { diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index e32a7c48e..ea8fd965a 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -309,6 +309,16 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, return save_data_factory->Open(space, save_struct); } +ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) { + LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast<u8>(space)); + + if (save_data_factory == nullptr) { + return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound); + } + + return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space)); +} + ResultVal<FileSys::VirtualDir> OpenSDMC() { LOG_TRACE(Service_FS, "Opening SDMC"); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 6ca5c5636..2cbb70c87 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -45,6 +45,7 @@ ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId stora FileSys::ContentRecordType type); ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct); +ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); ResultVal<FileSys::VirtualDir> OpenSDMC(); std::unique_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index c1c83a11d..b9a1d5105 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -11,6 +11,7 @@ #include "common/assert.h" #include "common/common_types.h" +#include "common/hex_util.h" #include "common/logging/log.h" #include "common/string_util.h" #include "core/file_sys/directory.h" @@ -451,7 +452,147 @@ private: VfsDirectoryServiceWrapper backend; }; +class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { +public: + explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space) + : ServiceFramework("ISaveDataInfoReader") { + static const FunctionInfo functions[] = { + {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, + }; + RegisterHandlers(functions); + + FindAllSaves(space); + } + + void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) { + // Calculate how many entries we can fit in the output buffer + const u64 count_entries = ctx.GetWriteBufferSize() / sizeof(SaveDataInfo); + + // Cap at total number of entries. + const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index); + + // Determine data start and end + const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index); + const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries); + const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); + + next_entry_index += actual_entries; + + // Write the data to memory + ctx.WriteBuffer(begin, range_size); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(static_cast<u32>(actual_entries)); + } + +private: + static u64 stoull_be(std::string_view str) { + if (str.size() != 16) + return 0; + + const auto bytes = Common::HexStringToArray<0x8>(str); + u64 out{}; + std::memcpy(&out, bytes.data(), sizeof(u64)); + + return Common::swap64(out); + } + + void FindAllSaves(FileSys::SaveDataSpaceId space) { + const auto save_root = OpenSaveDataSpace(space); + ASSERT(save_root.Succeeded()); + + for (const auto& type : (*save_root)->GetSubdirectories()) { + if (type->GetName() == "save") { + for (const auto& save_id : type->GetSubdirectories()) { + for (const auto& user_id : save_id->GetSubdirectories()) { + const auto save_id_numeric = stoull_be(save_id->GetName()); + auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName()); + std::reverse(user_id_numeric.begin(), user_id_numeric.end()); + + if (save_id_numeric != 0) { + // System Save Data + info.emplace_back(SaveDataInfo{ + 0, + space, + FileSys::SaveDataType::SystemSaveData, + {}, + user_id_numeric, + save_id_numeric, + 0, + user_id->GetSize(), + {}, + }); + + continue; + } + + for (const auto& title_id : user_id->GetSubdirectories()) { + const auto device = + std::all_of(user_id_numeric.begin(), user_id_numeric.end(), + [](u8 val) { return val == 0; }); + info.emplace_back(SaveDataInfo{ + 0, + space, + device ? FileSys::SaveDataType::DeviceSaveData + : FileSys::SaveDataType::SaveData, + {}, + user_id_numeric, + save_id_numeric, + stoull_be(title_id->GetName()), + title_id->GetSize(), + {}, + }); + } + } + } + } else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) { + // Temporary Storage + for (const auto& user_id : type->GetSubdirectories()) { + for (const auto& title_id : user_id->GetSubdirectories()) { + if (!title_id->GetFiles().empty() || + !title_id->GetSubdirectories().empty()) { + auto user_id_numeric = + Common::HexStringToArray<0x10>(user_id->GetName()); + std::reverse(user_id_numeric.begin(), user_id_numeric.end()); + + info.emplace_back(SaveDataInfo{ + 0, + space, + FileSys::SaveDataType::TemporaryStorage, + {}, + user_id_numeric, + stoull_be(type->GetName()), + stoull_be(title_id->GetName()), + title_id->GetSize(), + {}, + }); + } + } + } + } + } + } + + struct SaveDataInfo { + u64_le save_id_unknown; + FileSys::SaveDataSpaceId space; + FileSys::SaveDataType type; + INSERT_PADDING_BYTES(0x6); + std::array<u8, 0x10> user_id; + u64_le save_id; + u64_le title_id; + u64_le save_image_size; + INSERT_PADDING_BYTES(0x28); + }; + static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size."); + + std::vector<SaveDataInfo> info; + u64 next_entry_index = 0; +}; + FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { + // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "MountContent"}, {1, &FSP_SRV::Initialize, "Initialize"}, @@ -485,7 +626,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { {58, nullptr, "ReadSaveDataFileSystemExtraData"}, {59, nullptr, "WriteSaveDataFileSystemExtraData"}, {60, nullptr, "OpenSaveDataInfoReader"}, - {61, nullptr, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, + {61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, {62, nullptr, "OpenCacheStorageList"}, {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, {65, nullptr, "UpdateSaveDataMacForDebug"}, @@ -544,6 +685,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { {1009, nullptr, "GetAndClearMemoryReportInfo"}, {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, }; + // clang-format on RegisterHandlers(functions); } @@ -618,6 +760,15 @@ void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { MountSaveData(ctx); } +void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto space = rp.PopRaw<FileSys::SaveDataSpaceId>(); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space)); +} + void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 4aa0358cb..e7abec0a3 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -25,6 +25,7 @@ private: void CreateSaveData(Kernel::HLERequestContext& ctx); void MountSaveData(Kernel::HLERequestContext& ctx); void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); + void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 1ef789bd0..ff9b64be4 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -392,8 +392,10 @@ std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { } void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { + styleset_changed_event->Signal(); hold_type = joy_hold_type; } + Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { return hold_type; } diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 07c1381fe..1d2978f24 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/ns/ns.h" @@ -118,7 +121,7 @@ public: {305, nullptr, "TerminateSystemApplet"}, {306, nullptr, "LaunchOverlayApplet"}, {307, nullptr, "TerminateOverlayApplet"}, - {400, nullptr, "GetApplicationControlData"}, + {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, {401, nullptr, "InvalidateAllApplicationControlCache"}, {402, nullptr, "RequestDownloadApplicationControlData"}, {403, nullptr, "GetMaxApplicationControlCacheCount"}, @@ -243,6 +246,65 @@ public: RegisterHandlers(functions); } + + void GetApplicationControlData(Kernel::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(); + + const FileSys::PatchManager pm{title_id}; + const auto control = pm.GetControlMetadata(); + + std::vector<u8> out; + + if (control.first != nullptr) { + if (size < 0x4000) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min=0x4000)", + size); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultCode(-1)); + return; + } + + out.resize(0x4000); + const auto bytes = control.first->GetRawBytes(); + std::memcpy(out.data(), bytes.data(), bytes.size()); + } else { + LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", + title_id); + out.resize(std::min<u64>(0x4000, size)); + } + + if (control.second != nullptr) { + if (size < 0x4000 + control.second->GetSize()) { + LOG_ERROR(Service_NS, + "output buffer is too small! (actual={:016X}, expected_min={:016X})", + size, 0x4000 + control.second->GetSize()); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(DarkLordZach): Find a better error code for this. + rb.Push(ResultCode(-1)); + return; + } + + out.resize(0x4000 + control.second->GetSize()); + control.second->Read(out.data() + 0x4000, control.second->GetSize()); + } else { + LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", + title_id); + } + + ctx.WriteBuffer(out); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(static_cast<u32>(out.size())); + } }; class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp index 44a6717d0..69c260408 100644 --- a/src/core/hle/service/spl/module.cpp +++ b/src/core/hle/service/spl/module.cpp @@ -3,18 +3,23 @@ // Refer to the license.txt file included. #include <algorithm> +#include <chrono> #include <cstdlib> +#include <ctime> +#include <functional> #include <vector> #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/spl/csrng.h" #include "core/hle/service/spl/module.h" #include "core/hle/service/spl/spl.h" +#include "core/settings.h" namespace Service::SPL { Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) - : ServiceFramework(name), module(std::move(module)) {} + : ServiceFramework(name), module(std::move(module)), + rng(Settings::values.rng_seed.value_or(std::time(nullptr))) {} Module::Interface::~Interface() = default; @@ -24,7 +29,7 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { std::size_t size = ctx.GetWriteBufferSize(); std::vector<u8> data(size); - std::generate(data.begin(), data.end(), std::rand); + std::generate(data.begin(), data.end(), rng); ctx.WriteBuffer(data); diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h index 48fda6099..afa1f0295 100644 --- a/src/core/hle/service/spl/module.h +++ b/src/core/hle/service/spl/module.h @@ -4,6 +4,7 @@ #pragma once +#include <random> #include "core/hle/service/service.h" namespace Service::SPL { @@ -19,6 +20,9 @@ public: protected: std::shared_ptr<Module> module; + + private: + std::mt19937 rng; }; }; diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp index 18a5d71d5..e3cbd7004 100644 --- a/src/core/hle/service/time/interface.cpp +++ b/src/core/hle/service/time/interface.cpp @@ -21,7 +21,7 @@ Time::Time(std::shared_ptr<Module> time, const char* name) {102, nullptr, "GetStandardUserSystemClockInitialYear"}, {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"}, - {400, nullptr, "GetClockSnapshot"}, + {400, &Time::GetClockSnapshot, "GetClockSnapshot"}, {401, nullptr, "GetClockSnapshotFromSystemClockContext"}, {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"}, {501, nullptr, "CalculateSpanBetween"}, diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 28fd8debc..85e7b1195 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -15,6 +15,44 @@ namespace Service::Time { +static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, + CalendarAdditionalInfo& additional_info, + [[maybe_unused]] const TimeZoneRule& /*rule*/) { + const std::time_t time(posix_time); + const std::tm* tm = std::localtime(&time); + if (tm == nullptr) { + calendar_time = {}; + additional_info = {}; + return; + } + calendar_time.year = tm->tm_year + 1900; + calendar_time.month = tm->tm_mon + 1; + calendar_time.day = tm->tm_mday; + calendar_time.hour = tm->tm_hour; + calendar_time.minute = tm->tm_min; + calendar_time.second = tm->tm_sec; + + additional_info.day_of_week = tm->tm_wday; + additional_info.day_of_year = tm->tm_yday; + std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); + additional_info.utc_offset = 0; +} + +static u64 CalendarToPosix(const CalendarTime& calendar_time, + [[maybe_unused]] const TimeZoneRule& /*rule*/) { + std::tm time{}; + time.tm_year = calendar_time.year - 1900; + time.tm_mon = calendar_time.month - 1; + time.tm_mday = calendar_time.day; + + time.tm_hour = calendar_time.hour; + time.tm_min = calendar_time.minute; + time.tm_sec = calendar_time.second; + + std::time_t epoch_time = std::mktime(&time); + return static_cast<u64>(epoch_time); +} + class ISystemClock final : public ServiceFramework<ISystemClock> { public: ISystemClock() : ServiceFramework("ISystemClock") { @@ -80,8 +118,8 @@ public: {5, nullptr, "GetTimeZoneRuleVersion"}, {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, - {201, nullptr, "ToPosixTime"}, - {202, nullptr, "ToPosixTimeWithMyRule"}, + {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, + {202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, }; RegisterHandlers(functions); } @@ -151,24 +189,29 @@ private: rb.PushRaw(additional_info); } - void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, - CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { - std::time_t t(posix_time); - std::tm* tm = std::localtime(&t); - if (!tm) { - return; - } - calendar_time.year = tm->tm_year + 1900; - calendar_time.month = tm->tm_mon + 1; - calendar_time.day = tm->tm_mday; - calendar_time.hour = tm->tm_hour; - calendar_time.minute = tm->tm_min; - calendar_time.second = tm->tm_sec; - - additional_info.day_of_week = tm->tm_wday; - additional_info.day_of_year = tm->tm_yday; - std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); - additional_info.utc_offset = 0; + void ToPosixTime(Kernel::HLERequestContext& ctx) { + // TODO(ogniK): Figure out how to handle multiple times + LOG_WARNING(Service_Time, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + auto calendar_time = rp.PopRaw<CalendarTime>(); + auto posix_time = CalendarToPosix(calendar_time, {}); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u32>(1); // Amount of times we're returning + ctx.WriteBuffer(&posix_time, sizeof(u64)); + } + + void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Time, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + auto calendar_time = rp.PopRaw<CalendarTime>(); + auto posix_time = CalendarToPosix(calendar_time, {}); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u32>(1); // Amount of times we're returning + ctx.WriteBuffer(&posix_time, sizeof(u64)); } }; @@ -207,6 +250,55 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c LOG_DEBUG(Service_Time, "called"); } +void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + IPC::RequestParser rp{ctx}; + auto unknown_u8 = rp.PopRaw<u8>(); + + ClockSnapshot clock_snapshot{}; + + const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count()}; + CalendarTime calendar_time{}; + const std::time_t time(time_since_epoch); + const std::tm* tm = std::localtime(&time); + if (tm == nullptr) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code + return; + } + SteadyClockTimePoint steady_clock_time_point{CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / + 1000}; + + LocationName location_name{"UTC"}; + calendar_time.year = tm->tm_year + 1900; + calendar_time.month = tm->tm_mon + 1; + calendar_time.day = tm->tm_mday; + calendar_time.hour = tm->tm_hour; + calendar_time.minute = tm->tm_min; + calendar_time.second = tm->tm_sec; + clock_snapshot.system_posix_time = time_since_epoch; + clock_snapshot.network_posix_time = time_since_epoch; + clock_snapshot.system_calendar_time = calendar_time; + clock_snapshot.network_calendar_time = calendar_time; + + CalendarAdditionalInfo additional_info{}; + PosixToCalendar(time_since_epoch, calendar_time, additional_info, {}); + + clock_snapshot.system_calendar_info = additional_info; + clock_snapshot.network_calendar_info = additional_info; + + clock_snapshot.steady_clock_timepoint = steady_clock_time_point; + clock_snapshot.location_name = location_name; + clock_snapshot.clock_auto_adjustment_enabled = 1; + clock_snapshot.ipc_u8 = unknown_u8; + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot)); +} + Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) : ServiceFramework(name), time(std::move(time)) {} diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 5659ecad3..77871ae07 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include "common/common_funcs.h" #include "core/hle/service/service.h" namespace Service::Time { @@ -53,6 +54,23 @@ struct SystemClockContext { static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext structure has incorrect size"); +struct ClockSnapshot { + SystemClockContext user_clock_context; + SystemClockContext network_clock_context; + s64_le system_posix_time; + s64_le network_posix_time; + CalendarTime system_calendar_time; + CalendarTime network_calendar_time; + CalendarAdditionalInfo system_calendar_info; + CalendarAdditionalInfo network_calendar_info; + SteadyClockTimePoint steady_clock_timepoint; + LocationName location_name; + u8 clock_auto_adjustment_enabled; + u8 ipc_u8; + INSERT_PADDING_BYTES(2); +}; +static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size"); + class Module final { public: class Interface : public ServiceFramework<Interface> { @@ -65,6 +83,7 @@ public: void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); void GetTimeZoneService(Kernel::HLERequestContext& ctx); void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); + void GetClockSnapshot(Kernel::HLERequestContext& ctx); protected: std::shared_ptr<Module> time; |
