diff options
| author | Zephyron <zephyron@citron-emu.orgq> | 2025-02-17 17:33:10 +1000 | 
|---|---|---|
| committer | Zephyron <zephyron@citron-emu.orgq> | 2025-02-17 17:33:10 +1000 | 
| commit | c5e480e55ddc3183c48148daaa14c00ada855fee (patch) | |
| tree | 36613554e13c7526fc106b59b80c49bb1c893392 | |
| parent | 1c9e17496b6f9f4b083c62aa25548617dd179a8b (diff) | |
feat: Add Home Menu launch support and system improvements
This commit adds support for launching the system Home Menu and implements
several system-level improvements:
- Add Home Menu launch functionality through new UI action
- Implement shutdown/reboot sequence handlers in GlobalStateController
- Add support for reserved region extra size in page tables
- Enhance audio controller with output management
- Expand parental control service capabilities
- Add profile service improvements for user management
Technical changes:
- Add OnHomeMenu() handler to launch QLaunch system applet
- Implement m_alias_region_extra_size tracking in page tables
- Add new CreateProcessFlag for reserved region extra size
- Expand audio controller interface with output management
- Add self-controller methods to various services
- Implement play timer and profile service improvements
The changes primarily focus on system menu integration and core service
improvements to better support system functionality.
| -rw-r--r-- | src/citron/main.cpp | 41 | ||||
| -rw-r--r-- | src/citron/main.h | 1 | ||||
| -rw-r--r-- | src/citron/main.ui | 111 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process_page_table.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_types.h | 7 | ||||
| -rw-r--r-- | src/core/hle/service/acc/acc.cpp | 27 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/all_system_applet_proxies_service.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/all_system_applet_proxies_service.h | 5 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/global_state_controller.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/am/service/global_state_controller.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_controller.cpp | 57 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_controller.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/parental_control_service.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/parental_control_service.h | 2 | 
16 files changed, 206 insertions, 115 deletions
diff --git a/src/citron/main.cpp b/src/citron/main.cpp index c30395310..cb6cedd19 100644 --- a/src/citron/main.cpp +++ b/src/citron/main.cpp @@ -1584,6 +1584,7 @@ void GMainWindow::ConnectMenuEvents() {                   [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });      connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);      connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu); +    connect_menu(ui->action_Load_Home_Menu, &GMainWindow::OnHomeMenu);      connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);      // TAS @@ -1619,7 +1620,8 @@ void GMainWindow::UpdateMenuState() {                                      ui->action_Load_Cabinet_Restorer,                                      ui->action_Load_Cabinet_Formatter,                                      ui->action_Load_Mii_Edit, -                                    ui->action_Open_Controller_Menu}; +                                    ui->action_Open_Controller_Menu, +                                    ui->action_Load_Home_Menu};      for (QAction* action : running_actions) {          action->setEnabled(emulation_running); @@ -5324,3 +5326,40 @@ int main(int argc, char* argv[]) {      detached_tasks.WaitForAllTasks();      return result;  } + +void GMainWindow::OnHomeMenu() { +    constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch); + +    // Check if system NAND contents are available +    auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); +    if (!bis_system) { +        QMessageBox::warning(this, tr("System Error"), +                           tr("System NAND contents not found. Please verify your firmware installation.")); +        return; +    } + +    // Try to get the QLaunch NCA +    auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); +    if (!qlaunch_nca) { +        QMessageBox::warning(this, tr("System Error"), +                           tr("Home Menu applet not found. Please verify your firmware installation.")); +        return; +    } + +    // Set up applet parameters +    Service::AM::FrontendAppletParameters params{ +        .program_id = QLaunchId, +        .applet_id = Service::AM::AppletId::QLaunch, +        .applet_type = Service::AM::AppletType::SystemApplet +    }; + +    // Configure system for QLaunch +    system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch); + +    // Get path and launch +    const auto nca_path = QString::fromStdString(qlaunch_nca->GetFullPath()); +    UISettings::values.roms_path = QFileInfo(nca_path).path().toStdString(); + +    // Launch QLaunch with proper parameters +    BootGame(nca_path, params); +} diff --git a/src/citron/main.h b/src/citron/main.h index 4822a8981..8a2771760 100644 --- a/src/citron/main.h +++ b/src/citron/main.h @@ -407,6 +407,7 @@ private slots:      void OnShutdownBeginDialog();      void OnEmulationStopped();      void OnEmulationStopTimeExpired(); +    void OnHomeMenu();  private:      QString GetGameListErrorRemoving(InstalledEntryType type) const; diff --git a/src/citron/main.ui b/src/citron/main.ui index 56f1a358b..c68e0180a 100644 --- a/src/citron/main.ui +++ b/src/citron/main.ui @@ -17,91 +17,6 @@     <iconset resource="citron.qrc">      <normaloff>:/img/citron.ico</normaloff>:/img/citron.ico</iconset>    </property> -  <property name="styleSheet"> -   <string notr="true">QMainWindow { -    background-color: #2D2D2D; -} - -QMenuBar { -    background-color: #333333; -    color: #E0E0E0; -    border-bottom: 1px solid #404040; -    padding: 2px; -} - -QMenuBar::item { -    padding: 4px 8px; -    background: transparent; -    border-radius: 4px; -} - -QMenuBar::item:selected { -    background: #404040; -} - -QMenuBar::item:pressed { -    background: #505050; -} - -QMenu { -    background-color: #333333; -    border: 1px solid #404040; -    padding: 4px; -} - -QMenu::item { -    padding: 6px 24px 6px 12px; -    color: #E0E0E0; -    border-radius: 4px; -} - -QMenu::item:selected { -    background-color: #404040; -} - -QMenu::separator { -    height: 1px; -    background: #404040; -    margin: 4px 0px; -} - -QStatusBar { -    background-color: #333333; -    color: #E0E0E0; -    border-top: 1px solid #404040; -} - -QDockWidget { -    border: 1px solid #404040; -    titlebar-close-icon: url(close.png); -} - -QDockWidget::title { -    background: #333333; -    padding: 6px; -    color: #E0E0E0; -} - -QToolBar { -    background: #333333; -    border: none; -    spacing: 3px; -    padding: 3px; -} - -QToolButton { -    border-radius: 4px; -    padding: 4px; -} - -QToolButton:hover { -    background-color: #404040; -} - -QToolButton:pressed { -    background-color: #505050; -}</string> -  </property>    <property name="tabShape">     <enum>QTabWidget::Rounded</enum>    </property> @@ -130,7 +45,7 @@ QToolButton:pressed {       <x>0</x>       <y>0</y>       <width>1280</width> -     <height>29</height> +     <height>21</height>      </rect>     </property>     <widget class="QMenu" name="menu_File"> @@ -254,6 +169,7 @@ QToolButton:pressed {      <addaction name="action_Install_Firmware"/>      <addaction name="action_Verify_installed_contents"/>      <addaction name="separator"/> +    <addaction name="action_Load_Home_Menu"/>      <addaction name="menu_cabinet_applet"/>      <addaction name="action_Load_Album"/>      <addaction name="action_Load_Mii_Edit"/> @@ -266,7 +182,6 @@ QToolButton:pressed {      <property name="title">       <string>&Help</string>      </property> -    <addaction name="action_Report_Compatibility"/>      <addaction name="action_About"/>     </widget>     <addaction name="menu_File"/> @@ -322,7 +237,7 @@ QToolButton:pressed {    </action>    <action name="action_About">     <property name="text"> -    <string>&About citron</string> +    <string>&About Citron</string>     </property>    </action>    <action name="action_Single_Window_Mode"> @@ -457,7 +372,15 @@ QToolButton:pressed {    </action>    <action name="action_Open_citron_Folder">     <property name="text"> -    <string>Open &citron Folder</string> +    <string>Open &Citron Folder</string> +   </property> +  </action> +  <action name="action_Load_Home_Menu"> +   <property name="text"> +    <string>Launch System Menu</string> +   </property> +   <property name="toolTip"> +    <string>Launch the system Home Menu</string>     </property>    </action>    <action name="action_Capture_Screenshot"> @@ -556,16 +479,6 @@ QToolButton:pressed {      <string>Install Decryption Keys</string>     </property>    </action> -  <action name="actionSave"> -   <property name="text"> -    <string>&Save</string> -   </property> -  </action> -  <action name="actionLoad"> -   <property name="text"> -    <string>&Load</string> -   </property> -  </action>   </widget>   <resources>    <include location="citron.qrc"/> diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 5e00f0c81..5d5e3d002 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -172,6 +172,7 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start      m_mapped_unsafe_physical_memory = 0;      m_mapped_insecure_memory = 0;      m_mapped_ipc_server_memory = 0; +    m_alias_region_extra_size = 0;      m_memory_block_slab_manager =          m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 939b8a7ae..1a6f90ec2 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -208,6 +208,7 @@ private:      size_t m_mapped_unsafe_physical_memory{};      size_t m_mapped_insecure_memory{};      size_t m_mapped_ipc_server_memory{}; +    size_t m_alias_region_extra_size{};      mutable KLightLock m_general_lock;      mutable KLightLock m_map_physical_memory_lock;      KLightLock m_device_map_lock; @@ -715,6 +716,10 @@ public:          return m_address_space_width;      } +    size_t GetReservedRegionExtraSize() const { +        return m_alias_region_extra_size; +    } +  public:      // Linear mapped      static u8* GetLinearMappedVirtualPointer(KernelCore& kernel, KPhysicalAddress addr) { diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h index 346d7ca08..4b9942d50 100644 --- a/src/core/hle/kernel/k_process_page_table.h +++ b/src/core/hle/kernel/k_process_page_table.h @@ -472,6 +472,10 @@ public:      const KPageTable& GetBasePageTable() const {          return m_page_table;      } + +    size_t GetReservedRegionExtraSize() const { +        return m_page_table.GetReservedRegionExtraSize(); +    }  };  } // namespace Kernel diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index e301f67c5..e4f60d953 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -153,6 +153,7 @@ enum class InfoType : u32 {      ThreadTickCount = 25,      IsSvcPermitted = 26,      IoRegionHint = 27, +    ReservedRegionExtraSize = 28,      MesosphereMeta = 65000,      MesosphereCurrentProcess = 65001, @@ -643,9 +644,13 @@ enum class CreateProcessFlag : u32 {      // 11.x+ DisableDeviceAddressSpaceMerge.      DisableDeviceAddressSpaceMerge = (1 << 12), +    // 13.x+ EnableReservedRegionExtraSize. +    EnableReservedRegionExtraSize = (1 << 13), +      // Mask of all flags.      All = Is64Bit | AddressSpaceMask | EnableDebug | EnableAslr | IsApplication | -          PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge, +          PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge | +          EnableReservedRegionExtraSize,  };  DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag); diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 9f40c5425..e628c025c 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -317,6 +317,10 @@ public:              {1, &IProfileCommon::GetBase, "GetBase"},              {10, &IProfileCommon::GetImageSize, "GetImageSize"},              {11, &IProfileCommon::LoadImage, "LoadImage"}, +            {20, &IProfileCommon::GetImageSize, "GetLargeImageSize"}, +            {21, &IProfileCommon::LoadImage, "LoadLargeImage"}, +            {30, &IProfileCommon::Unknown, "GetImageId"}, +            {40, &IProfileCommon::GetStableUserId, "GetStableUserId"},          };          RegisterHandlers(functions); @@ -486,6 +490,20 @@ protected:          rb.Push(ResultSuccess);      } +    void Unknown(HLERequestContext& ctx) { +        LOG_WARNING(Service_ACC, "(STUBBED) called"); +        IPC::ResponseBuilder rb{ctx, 3}; +        rb.Push(ResultSuccess); +        rb.Push(0); +    } + +    void GetStableUserId(HLERequestContext& ctx) { +        LOG_DEBUG(Service_ACC, "called"); +        IPC::ResponseBuilder rb{ctx, 3}; +        rb.Push(ResultSuccess); +        rb.Push(user_id.Hash()); +    } +      ProfileManager& profile_manager;      Common::UUID user_id{}; ///< The user id this profile refers to.  }; @@ -500,8 +518,13 @@ public:  class IProfileEditor final : public IProfileCommon {  public:      explicit IProfileEditor(Core::System& system_, Common::UUID user_id_, -                            ProfileManager& profile_manager_) -        : IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {} +                          ProfileManager& profile_manager_) +        : IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} { +        static const FunctionInfo functions[] = { +            {30, &IProfileEditor::Unknown, "Unknown"}, +        }; +        RegisterHandlers(functions); +    }  };  class ISessionObject final : public ServiceFramework<ISessionObject> { diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index bc9c86c55..e44037d30 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp @@ -4,6 +4,7 @@  #include "core/core.h"  #include "core/hle/service/am/applet_manager.h"  #include "core/hle/service/am/service/all_system_applet_proxies_service.h" +#include "core/hle/service/am/service/global_state_controller.h"  #include "core/hle/service/am/service/library_applet_proxy.h"  #include "core/hle/service/am/service/system_applet_proxy.h"  #include "core/hle/service/am/window_system.h" @@ -23,6 +24,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys          {350, nullptr, "OpenSystemApplicationProxy"},          {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},          {410, nullptr, "GetSystemAppletControllerForDebug"}, +        {450, D<&IAllSystemAppletProxiesService::GetGlobalStateController>, "GetGlobalStateController"},          {1000, nullptr, "GetDebugFunctions"},      };      // clang-format on @@ -73,6 +75,13 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(          this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));  } +Result IAllSystemAppletProxiesService::GetGlobalStateController( +    Out<SharedPointer<IGlobalStateController>> out_controller) { +    LOG_DEBUG(Service_AM, "called"); +    *out_controller = std::make_shared<IGlobalStateController>(this->system); +    R_SUCCEED(); +} +  std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(      ProcessId process_id) {      return m_window_system.GetByAppletResourceUserId(process_id.pid); diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h index e3e79dc4f..344d93b13 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.h +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h @@ -5,6 +5,7 @@  #include "core/hle/service/cmif_types.h"  #include "core/hle/service/service.h" +#include "core/hle/service/am/service/global_state_controller.h"  namespace Service { @@ -14,6 +15,7 @@ struct Applet;  struct AppletAttribute;  class ILibraryAppletProxy;  class ISystemAppletProxy; +class IGlobalStateController;  class WindowSystem;  class IAllSystemAppletProxiesService final @@ -34,7 +36,8 @@ private:          Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,          InCopyHandle<Kernel::KProcess> process_handle); -private: +    Result GetGlobalStateController(Out<SharedPointer<IGlobalStateController>> out_controller); +      std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);      WindowSystem& m_window_system; diff --git a/src/core/hle/service/am/service/global_state_controller.cpp b/src/core/hle/service/am/service/global_state_controller.cpp index dba5d3613..e1ffff919 100644 --- a/src/core/hle/service/am/service/global_state_controller.cpp +++ b/src/core/hle/service/am/service/global_state_controller.cpp @@ -15,8 +15,8 @@ IGlobalStateController::IGlobalStateController(Core::System& system_)          {0, nullptr, "RequestToEnterSleep"},          {1, nullptr, "EnterSleep"},          {2, nullptr, "StartSleepSequence"}, -        {3, nullptr, "StartShutdownSequence"}, -        {4, nullptr, "StartRebootSequence"}, +        {3, D<&IGlobalStateController::StartShutdownSequence>, "StartShutdownSequence"}, +        {4, D<&IGlobalStateController::StartRebootSequence>, "StartRebootSequence"},          {9, nullptr, "IsAutoPowerDownRequested"},          {10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},          {11, nullptr, "NotifyCecSettingsChanged"}, @@ -58,4 +58,16 @@ Result IGlobalStateController::OpenCradleFirmwareUpdater(      R_SUCCEED();  } +Result IGlobalStateController::StartShutdownSequence() { +    LOG_INFO(Service_AM, "called"); +    system.Exit(); +    R_SUCCEED(); +} + +Result IGlobalStateController::StartRebootSequence() { +    LOG_INFO(Service_AM, "called"); +    system.Exit(); +    R_SUCCEED(); +} +  } // namespace Service::AM diff --git a/src/core/hle/service/am/service/global_state_controller.h b/src/core/hle/service/am/service/global_state_controller.h index 67c753513..83efb57df 100644 --- a/src/core/hle/service/am/service/global_state_controller.h +++ b/src/core/hle/service/am/service/global_state_controller.h @@ -18,6 +18,8 @@ public:      ~IGlobalStateController() override;  private: +    Result StartShutdownSequence(); +    Result StartRebootSequence();      Result LoadAndApplyIdlePolicySettings();      Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);      Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp index 300764ad6..c725e05fc 100644 --- a/src/core/hle/service/audio/audio_controller.cpp +++ b/src/core/hle/service/audio/audio_controller.cpp @@ -11,8 +11,19 @@  namespace Service::Audio {  IAudioController::IAudioController(Core::System& system_) -    : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} { -    // clang-format off +    : ServiceFramework{system_, "audctl"} +    , service_context{system, "audctl"} +    , m_current_output_target{1}  // Initialize with default values +    , m_current_parameter{0x1388} +    , m_current_volume{100} { + +    // Create notification event first +    notification_event = service_context.CreateEvent("IAudioController:NotificationEvent"); + +    // Get system settings service +    m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); + +    // Register handlers      static const FunctionInfo functions[] = {          {0, nullptr, "GetTargetVolume"},          {1, nullptr, "SetTargetVolume"}, @@ -67,15 +78,15 @@ IAudioController::IAudioController(Core::System& system_)          {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},          {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},          {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, -        {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, +        {5000, D<&IAudioController::GetSelfController>, "GetSelfController"}, +        {50001, D<&IAudioController::SetAudioControllerOutput>, "SetAudioControllerOutput"},      }; -    // clang-format on -      RegisterHandlers(functions); -    m_set_sys = -        system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); -    notification_event = service_context.CreateEvent("IAudioController:NotificationEvent"); +    // Signal initial state +    if (notification_event) { +        notification_event->Signal(); +    }  }  IAudioController::~IAudioController() { @@ -176,4 +187,34 @@ Result IAudioController::AcquireTargetNotification(      R_SUCCEED();  } +Result IAudioController::SetAudioControllerOutput(u32 output_target, u32 parameter, u32 volume) { +    LOG_DEBUG(Audio, "called. output_target={}, parameter={}, volume={}", output_target, parameter, volume); + +    if (!notification_event) { +        LOG_ERROR(Audio, "Notification event not initialized"); +        R_THROW(ResultCode::ResultInvalidState); +    } + +    m_current_output_target = output_target; +    m_current_parameter = parameter; +    m_current_volume = volume; + +    notification_event->Signal(); +    R_SUCCEED(); +} + +Result IAudioController::GetSelfController(Out<SharedPointer<IAudioController>> out_controller) { +    LOG_DEBUG(Audio, "called"); + +    // Use ServiceFramework's built-in method to get a shared pointer +    *out_controller = SharedPointer<IAudioController>(this); + +    // Signal notification event since we're returning a new interface +    if (notification_event) { +        notification_event->Signal(); +    } + +    R_SUCCEED(); +} +  } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h index d37c4843e..98d7ecf89 100644 --- a/src/core/hle/service/audio/audio_controller.h +++ b/src/core/hle/service/audio/audio_controller.h @@ -6,6 +6,7 @@  #include "core/hle/service/cmif_types.h"  #include "core/hle/service/service.h"  #include "core/hle/service/set/settings_types.h" +#include "core/hle/result.h"  namespace Core {  class System; @@ -17,6 +18,10 @@ class ISystemSettingsServer;  namespace Service::Audio { +namespace ResultCode { +    constexpr Result ResultInvalidState{ErrorModule::Audio, 1}; +} // namespace ResultCode +  class IAudioController final : public ServiceFramework<IAudioController> {  public:      explicit IAudioController(Core::System& system_); @@ -49,11 +54,18 @@ private:      Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);      Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);      Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event); +    Result SetAudioControllerOutput(u32 output_target, u32 parameter, u32 volume); +    Result GetSelfController(Out<SharedPointer<IAudioController>> out_controller);      KernelHelpers::ServiceContext service_context;      Kernel::KEvent* notification_event;      std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; + +    // Add state tracking +    u32 m_current_output_target{0}; +    u32 m_current_parameter{0}; +    u32 m_current_volume{0};  };  } // namespace Service::Audio diff --git a/src/core/hle/service/pctl/parental_control_service.cpp b/src/core/hle/service/pctl/parental_control_service.cpp index f57f2f157..3d156e87a 100644 --- a/src/core/hle/service/pctl/parental_control_service.cpp +++ b/src/core/hle/service/pctl/parental_control_service.cpp @@ -77,7 +77,7 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili          {1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},          {1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},          {1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"}, -        {1454, nullptr, "GetPlayTimerRemainingTime"}, +        {1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"},          {1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},          {1456, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"},          {1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"}, @@ -117,6 +117,7 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili          {2014, nullptr, "FinishSynchronizeParentalControlSettings"},          {2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},          {2016, nullptr, "RequestUpdateExemptionListAsync"}, +        {145601, D<&IParentalControlService::GetSelfController>, "GetSelfController"},      };      // clang-format on      RegisterHandlers(functions); @@ -431,4 +432,22 @@ Result IParentalControlService::ResetConfirmedStereoVisionPermission() {      R_SUCCEED();  } +Result IParentalControlService::GetSelfController(Out<SharedPointer<IParentalControlService>> out_controller) { +    LOG_DEBUG(Service_PCTL, "called"); + +    // Return a shared pointer to this service instance +    *out_controller = SharedPointer<IParentalControlService>(this); + +    R_SUCCEED(); +} + +Result IParentalControlService::GetPlayTimerRemainingTime(Out<s32> out_remaining_time) { +    LOG_DEBUG(Service_PCTL, "called"); + +    // For now, return maximum time remaining since play timer is stubbed +    *out_remaining_time = std::numeric_limits<s32>::max(); + +    R_SUCCEED(); +} +  } // namespace Service::PCTL diff --git a/src/core/hle/service/pctl/parental_control_service.h b/src/core/hle/service/pctl/parental_control_service.h index 03dbaa2e5..121e67664 100644 --- a/src/core/hle/service/pctl/parental_control_service.h +++ b/src/core/hle/service/pctl/parental_control_service.h @@ -53,6 +53,8 @@ private:      Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);      Result SetStereoVisionRestriction(bool stereo_vision_restriction);      Result ResetConfirmedStereoVisionPermission(); +    Result GetSelfController(Out<SharedPointer<IParentalControlService>> out_controller); +    Result GetPlayTimerRemainingTime(Out<s32> out_remaining_time);      struct States {          u64 current_tid{};  | 
