summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.orgq>2025-02-17 17:33:10 +1000
committerZephyron <zephyron@citron-emu.orgq>2025-02-17 17:33:10 +1000
commitc5e480e55ddc3183c48148daaa14c00ada855fee (patch)
tree36613554e13c7526fc106b59b80c49bb1c893392 /src
parent1c9e17496b6f9f4b083c62aa25548617dd179a8b (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.
Diffstat (limited to 'src')
-rw-r--r--src/citron/main.cpp41
-rw-r--r--src/citron/main.h1
-rw-r--r--src/citron/main.ui111
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp1
-rw-r--r--src/core/hle/kernel/k_page_table_base.h5
-rw-r--r--src/core/hle/kernel/k_process_page_table.h4
-rw-r--r--src/core/hle/kernel/svc_types.h7
-rw-r--r--src/core/hle/service/acc/acc.cpp27
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.cpp9
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.h5
-rw-r--r--src/core/hle/service/am/service/global_state_controller.cpp16
-rw-r--r--src/core/hle/service/am/service/global_state_controller.h2
-rw-r--r--src/core/hle/service/audio/audio_controller.cpp57
-rw-r--r--src/core/hle/service/audio/audio_controller.h12
-rw-r--r--src/core/hle/service/pctl/parental_control_service.cpp21
-rw-r--r--src/core/hle/service/pctl/parental_control_service.h2
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>&amp;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>&amp;About citron</string>
+ <string>&amp;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 &amp;citron Folder</string>
+ <string>Open &amp;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>&amp;Save</string>
- </property>
- </action>
- <action name="actionLoad">
- <property name="text">
- <string>&amp;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{};