summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/k_client_session.cpp8
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp40
-rw-r--r--src/core/hle/kernel/k_process.cpp16
-rw-r--r--src/core/hle/kernel/k_server_session.cpp36
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/k_thread_local_page.cpp4
-rw-r--r--src/core/hle/kernel/k_transfer_memory.cpp4
-rw-r--r--src/core/hle/kernel/kernel.cpp69
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/svc/svc_code_memory.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_device_address_space.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_event.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp8
-rw-r--r--src/core/hle/kernel/svc/svc_port.cpp8
-rw-r--r--src/core/hle/kernel/svc/svc_resource_limit.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_session.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_transfer_memory.cpp4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp5
-rw-r--r--src/core/hle/service/am/am.cpp10
-rw-r--r--src/core/hle/service/am/am.h6
-rw-r--r--src/core/hle/service/am/applet.h6
-rw-r--r--src/core/hle/service/am/applet_data_broker.cpp4
-rw-r--r--src/core/hle/service/am/applet_manager.cpp18
-rw-r--r--src/core/hle/service/am/display_layer_manager.cpp151
-rw-r--r--src/core/hle/service/am/display_layer_manager.h62
-rw-r--r--src/core/hle/service/am/frontend/applet_web_browser.cpp2
-rw-r--r--src/core/hle/service/am/library_applet_storage.cpp4
-rw-r--r--src/core/hle/service/am/managed_layer_holder.cpp59
-rw-r--r--src/core/hle/service/am/managed_layer_holder.h32
-rw-r--r--src/core/hle/service/am/process.cpp4
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.cpp13
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.h8
-rw-r--r--src/core/hle/service/am/service/application_functions.cpp30
-rw-r--r--src/core/hle/service/am/service/application_functions.h1
-rw-r--r--src/core/hle/service/am/service/application_proxy.cpp9
-rw-r--r--src/core/hle/service/am/service/application_proxy.h3
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.cpp7
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.h7
-rw-r--r--src/core/hle/service/am/service/display_controller.cpp6
-rw-r--r--src/core/hle/service/am/service/library_applet_creator.cpp2
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.cpp17
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.h2
-rw-r--r--src/core/hle/service/am/service/self_controller.cpp53
-rw-r--r--src/core/hle/service/am/service/self_controller.h3
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/window_controller.cpp2
-rw-r--r--src/core/hle/service/am/system_buffer_manager.cpp80
-rw-r--r--src/core/hle/service/am/system_buffer_manager.h52
-rw-r--r--src/core/hle/service/audio/audctl.cpp201
-rw-r--r--src/core/hle/service/audio/audctl.h50
-rw-r--r--src/core/hle/service/audio/audio.cpp4
-rw-r--r--src/core/hle/service/audio/audio_controller.cpp174
-rw-r--r--src/core/hle/service/audio/audio_controller.h58
-rw-r--r--src/core/hle/service/caps/caps_a.cpp11
-rw-r--r--src/core/hle/service/caps/caps_a.h3
-rw-r--r--src/core/hle/service/erpt/erpt.cpp12
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.cpp9
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.h1
-rw-r--r--src/core/hle/service/glue/time/manager.cpp4
-rw-r--r--src/core/hle/service/glue/time/manager.h1
-rw-r--r--src/core/hle/service/glue/time/static.cpp41
-rw-r--r--src/core/hle/service/glue/time/time_zone.cpp36
-rw-r--r--src/core/hle/service/ns/account_proxy_interface.cpp21
-rw-r--r--src/core/hle/service/ns/account_proxy_interface.h16
-rw-r--r--src/core/hle/service/ns/application_manager_interface.cpp519
-rw-r--r--src/core/hle/service/ns/application_manager_interface.h62
-rw-r--r--src/core/hle/service/ns/application_version_interface.cpp33
-rw-r--r--src/core/hle/service/ns/application_version_interface.h16
-rw-r--r--src/core/hle/service/ns/content_management_interface.cpp72
-rw-r--r--src/core/hle/service/ns/content_management_interface.h25
-rw-r--r--src/core/hle/service/ns/develop_interface.cpp38
-rw-r--r--src/core/hle/service/ns/develop_interface.h16
-rw-r--r--src/core/hle/service/ns/document_interface.cpp38
-rw-r--r--src/core/hle/service/ns/document_interface.h22
-rw-r--r--src/core/hle/service/ns/download_task_interface.cpp39
-rw-r--r--src/core/hle/service/ns/download_task_interface.h20
-rw-r--r--src/core/hle/service/ns/dynamic_rights_interface.cpp62
-rw-r--r--src/core/hle/service/ns/dynamic_rights_interface.h22
-rw-r--r--src/core/hle/service/ns/ecommerce_interface.cpp27
-rw-r--r--src/core/hle/service/ns/ecommerce_interface.h16
-rw-r--r--src/core/hle/service/ns/factory_reset_interface.cpp27
-rw-r--r--src/core/hle/service/ns/factory_reset_interface.h16
-rw-r--r--src/core/hle/service/ns/ns.cpp903
-rw-r--r--src/core/hle/service/ns/ns.h133
-rw-r--r--src/core/hle/service/ns/ns_results.h (renamed from src/core/hle/service/ns/errors.h)0
-rw-r--r--src/core/hle/service/ns/ns_types.h111
-rw-r--r--src/core/hle/service/ns/pdm_qry.cpp67
-rw-r--r--src/core/hle/service/ns/platform_service_manager.cpp (renamed from src/core/hle/service/ns/iplatform_service_manager.cpp)130
-rw-r--r--src/core/hle/service/ns/platform_service_manager.h (renamed from src/core/hle/service/ns/iplatform_service_manager.h)33
-rw-r--r--src/core/hle/service/ns/query_service.cpp57
-rw-r--r--src/core/hle/service/ns/query_service.h (renamed from src/core/hle/service/ns/pdm_qry.h)12
-rw-r--r--src/core/hle/service/ns/read_only_application_control_data_interface.cpp122
-rw-r--r--src/core/hle/service/ns/read_only_application_control_data_interface.h30
-rw-r--r--src/core/hle/service/ns/read_only_application_record_interface.cpp38
-rw-r--r--src/core/hle/service/ns/read_only_application_record_interface.h22
-rw-r--r--src/core/hle/service/ns/service_getter_interface.cpp120
-rw-r--r--src/core/hle/service/ns/service_getter_interface.h47
-rw-r--r--src/core/hle/service/ns/system_update_control.cpp44
-rw-r--r--src/core/hle/service/ns/system_update_control.h16
-rw-r--r--src/core/hle/service/ns/system_update_interface.cpp61
-rw-r--r--src/core/hle/service/ns/system_update_interface.h38
-rw-r--r--src/core/hle/service/ns/vulnerability_manager_interface.cpp31
-rw-r--r--src/core/hle/service/ns/vulnerability_manager_interface.h21
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp4
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp3
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h9
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp10
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h4
-rw-r--r--src/core/hle/service/nvnflinger/binder.h23
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp76
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h10
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.cpp32
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h8
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.h4
-rw-r--r--src/core/hle/service/nvnflinger/display.h55
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp65
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.h20
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.cpp (renamed from src/core/hle/service/vi/hos_binder_driver.cpp)31
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.h (renamed from src/core/hle/service/vi/hos_binder_driver.h)30
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp22
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.h16
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp333
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h166
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.cpp124
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.h65
-rw-r--r--src/core/hle/service/psc/time/static.cpp33
-rw-r--r--src/core/hle/service/psc/time/steady_clock.cpp25
-rw-r--r--src/core/hle/service/psc/time/system_clock.cpp8
-rw-r--r--src/core/hle/service/psc/time/time_zone_service.cpp32
-rw-r--r--src/core/hle/service/server_manager.cpp8
-rw-r--r--src/core/hle/service/service.cpp136
-rw-r--r--src/core/hle/service/service.h21
-rw-r--r--src/core/hle/service/services.cpp136
-rw-r--r--src/core/hle/service/services.h22
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp123
-rw-r--r--src/core/hle/service/vi/application_display_service.h34
-rw-r--r--src/core/hle/service/vi/application_root_service.cpp13
-rw-r--r--src/core/hle/service/vi/application_root_service.h12
-rw-r--r--src/core/hle/service/vi/conductor.cpp114
-rw-r--r--src/core/hle/service/vi/conductor.h57
-rw-r--r--src/core/hle/service/vi/container.cpp228
-rw-r--r--src/core/hle/service/vi/container.h92
-rw-r--r--src/core/hle/service/vi/display.h44
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp143
-rw-r--r--src/core/hle/service/vi/display/vi_display.h143
-rw-r--r--src/core/hle/service/vi/display_list.h83
-rw-r--r--src/core/hle/service/vi/layer.h79
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp18
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h118
-rw-r--r--src/core/hle/service/vi/layer_list.h69
-rw-r--r--src/core/hle/service/vi/manager_display_service.cpp46
-rw-r--r--src/core/hle/service/vi/manager_display_service.h21
-rw-r--r--src/core/hle/service/vi/manager_root_service.cpp14
-rw-r--r--src/core/hle/service/vi/manager_root_service.h14
-rw-r--r--src/core/hle/service/vi/service_creator.cpp5
-rw-r--r--src/core/hle/service/vi/service_creator.h9
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.cpp (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp)136
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.h (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.h)46
-rw-r--r--src/core/hle/service/vi/system_display_service.cpp66
-rw-r--r--src/core/hle/service/vi/system_display_service.h20
-rw-r--r--src/core/hle/service/vi/system_root_service.cpp11
-rw-r--r--src/core/hle/service/vi/system_root_service.h12
-rw-r--r--src/core/hle/service/vi/vi.cpp21
-rw-r--r--src/core/hle/service/vi/vi.h10
-rw-r--r--src/core/hle/service/vi/vi_types.h10
-rw-r--r--src/core/hle/service/vi/vsync_manager.cpp26
-rw-r--r--src/core/hle/service/vi/vsync_manager.h29
175 files changed, 4660 insertions, 3408 deletions
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 472e8571c..3e01e3b67 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -24,7 +24,9 @@ Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) {
// Create a session request.
KSessionRequest* request = KSessionRequest::Create(m_kernel);
R_UNLESS(request != nullptr, ResultOutOfResource);
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// Initialize the request.
request->Initialize(nullptr, address, size);
@@ -37,7 +39,9 @@ Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t
// Create a session request.
KSessionRequest* request = KSessionRequest::Create(m_kernel);
R_UNLESS(request != nullptr, ResultOutOfResource);
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// Initialize the request.
request->Initialize(event, address, size);
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 1dd86fb3c..19cdf4f3a 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -1305,11 +1305,11 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
// Ensure that we maintain the instruction cache.
bool reprotected_pages = false;
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (reprotected_pages && any_code_pages) {
InvalidateInstructionCache(m_kernel, this, dst_address, size);
}
- });
+ };
// Unmap.
{
@@ -1397,7 +1397,9 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// Close the opened pages when we're done with them.
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically.
- SCOPE_EXIT({ pg.Close(); });
+ SCOPE_EXIT {
+ pg.Close();
+ };
// Clear all the newly allocated pages.
for (const auto& it : pg) {
@@ -1603,7 +1605,9 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option));
// Ensure that the page group is closed when we're done working with it.
- SCOPE_EXIT({ pg.Close(); });
+ SCOPE_EXIT {
+ pg.Close();
+ };
// Clear all pages.
for (const auto& it : pg) {
@@ -2191,7 +2195,9 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
// Close the opened pages when we're done with them.
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically.
- SCOPE_EXIT({ pg.Close(); });
+ SCOPE_EXIT {
+ pg.Close();
+ };
// Clear all the newly allocated pages.
for (const auto& it : pg) {
@@ -2592,7 +2598,9 @@ Result KPageTableBase::UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddre
// Temporarily unlock ourselves, so that other operations can occur while we flush the
// region.
m_general_lock.Unlock();
- SCOPE_EXIT({ m_general_lock.Lock(); });
+ SCOPE_EXIT {
+ m_general_lock.Lock();
+ };
// Flush the region.
R_ASSERT(FlushDataCache(dst_address, size));
@@ -3311,10 +3319,10 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre
// Ensure we unmap the io memory when we're done with it.
const KPageProperties unmap_properties =
KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None};
- SCOPE_EXIT({
+ SCOPE_EXIT {
R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,
unmap_properties, OperationType::Unmap, true));
- });
+ };
// Read the memory.
const KProcessAddress read_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1));
@@ -3347,10 +3355,10 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd
// Ensure we unmap the io memory when we're done with it.
const KPageProperties unmap_properties =
KPageProperties{KMemoryPermission::None, false, false, DisableMergeAttribute::None};
- SCOPE_EXIT({
+ SCOPE_EXIT {
R_ASSERT(this->Operate(updater.GetPageList(), io_addr, map_size / PageSize, 0, false,
unmap_properties, OperationType::Unmap, true));
- });
+ };
// Write the memory.
const KProcessAddress write_addr = io_addr + (GetInteger(phys_addr) & (PageSize - 1));
@@ -4491,14 +4499,14 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// If the partial pages are mapped, an extra reference will have been opened. Otherwise, they'll
// free on scope exit.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (start_partial_page != 0) {
m_kernel.MemoryManager().Close(start_partial_page, 1);
}
if (end_partial_page != 0) {
m_kernel.MemoryManager().Close(end_partial_page, 1);
}
- });
+ };
ON_RESULT_FAILURE {
if (cur_mapped_addr != dst_addr) {
@@ -5166,10 +5174,10 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value));
// If we fail in the next bit (or retry), we need to cleanup the pages.
- auto pg_guard = SCOPE_GUARD({
+ auto pg_guard = SCOPE_GUARD {
pg.OpenFirst();
pg.Close();
- });
+ };
// Map the memory.
{
@@ -5694,7 +5702,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
// Ensure that any pages we track are closed on exit.
KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager());
- SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
+ SCOPE_EXIT {
+ pages_to_close.CloseAndReset();
+ };
// Make a page group representing the region to unmap.
this->MakePageGroup(pages_to_close, virt_addr, num_pages);
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 1bcc42890..cb9a11a63 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -77,7 +77,9 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process,
}
// Terminate and close the thread.
- SCOPE_EXIT({ cur_child->Close(); });
+ SCOPE_EXIT {
+ cur_child->Close();
+ };
if (const Result terminate_result = cur_child->Terminate();
ResultTerminationRequested == terminate_result) {
@@ -466,11 +468,11 @@ void KProcess::DoWorkerTaskImpl() {
Result KProcess::StartTermination() {
// Finalize the handle table when we're done, if the process isn't immortal.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (!m_is_immortal) {
this->FinalizeHandleTable();
}
- });
+ };
// Terminate child threads other than the current one.
R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel)));
@@ -964,7 +966,9 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
// Create a new thread for the process.
KThread* main_thread = KThread::Create(m_kernel);
R_UNLESS(main_thread != nullptr, ResultOutOfResource);
- SCOPE_EXIT({ main_thread->Close(); });
+ SCOPE_EXIT {
+ main_thread->Close();
+ };
// Initialize the thread.
R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0,
@@ -1155,7 +1159,9 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
// Ensure we maintain a clean state on exit.
- SCOPE_EXIT({ res_limit->Close(); });
+ SCOPE_EXIT {
+ res_limit->Close();
+ };
// Declare flags and code address.
Svc::CreateProcessFlag flag{};
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index adaabdd6d..40c3323ef 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -651,11 +651,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any special data.
if (src_header.GetHasSpecialHeader()) {
// After we process, make sure we track whether the receive list is broken.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
- });
+ };
// Process special data.
R_TRY(ProcessMessageSpecialData<false>(offset, dst_process, src_process, src_thread,
@@ -665,11 +665,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any pointer buffers.
for (auto i = 0; i < src_header.GetPointerCount(); ++i) {
// After we process, make sure we track whether the receive list is broken.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
- });
+ };
R_TRY(ProcessReceiveMessagePointerDescriptors(
offset, pointer_key, dst_page_table, src_page_table, dst_msg, src_msg, dst_recv_list,
@@ -680,11 +680,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any map alias buffers.
for (auto i = 0; i < src_header.GetMapAliasCount(); ++i) {
// After we process, make sure we track whether the receive list is broken.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (offset > dst_recv_list_idx) {
recv_list_broken = true;
}
- });
+ };
// We process in order send, recv, exch. Buffers after send (recv/exch) are ReadWrite.
const KMemoryPermission perm = (i >= src_header.GetSendCount())
@@ -702,11 +702,11 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m
// Process any raw data.
if (const auto raw_count = src_header.GetRawCount(); raw_count != 0) {
// After we process, make sure we track whether the receive list is broken.
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (offset + raw_count > dst_recv_list_idx) {
recv_list_broken = true;
}
- });
+ };
// Get the offset and size.
const size_t offset_words = offset * sizeof(u32);
@@ -1124,7 +1124,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server
client_thread->Open();
}
- SCOPE_EXIT({ client_thread->Close(); });
+ SCOPE_EXIT {
+ client_thread->Close();
+ };
// Set the request as our current.
m_current_request = request;
@@ -1174,7 +1176,9 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server
// Reply to the client.
{
// After we reply, close our reference to the request.
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// Get the event to check whether the request is async.
if (KEvent* event = request->GetEvent(); event != nullptr) {
@@ -1236,7 +1240,9 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff
}
// Close reference to the request once we're done processing it.
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// Extract relevant information from the request.
const uint64_t client_message = request->GetAddress();
@@ -1394,7 +1400,9 @@ void KServerSession::CleanupRequests() {
}
// Close a reference to the request once it's cleaned up.
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// Extract relevant information from the request.
const uint64_t client_message = request->GetAddress();
@@ -1491,7 +1499,9 @@ void KServerSession::OnClientClosed() {
ASSERT(thread != nullptr);
// Ensure that we close the request when done.
- SCOPE_EXIT({ request->Close(); });
+ SCOPE_EXIT {
+ request->Close();
+ };
// If we're terminating, close a reference to the thread and event.
if (terminate) {
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f13e232b2..e928cfebc 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -66,6 +66,7 @@ enum class SuspendType : u32 {
Debug = 2,
Backtrace = 3,
Init = 4,
+ System = 5,
Count,
};
@@ -84,8 +85,9 @@ enum class ThreadState : u16 {
DebugSuspended = (1 << (2 + SuspendShift)),
BacktraceSuspended = (1 << (3 + SuspendShift)),
InitSuspended = (1 << (4 + SuspendShift)),
+ SystemSuspended = (1 << (5 + SuspendShift)),
- SuspendFlagMask = ((1 << 5) - 1) << SuspendShift,
+ SuspendFlagMask = ((1 << 6) - 1) << SuspendShift,
};
DECLARE_ENUM_FLAG_OPERATORS(ThreadState);
diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp
index a632d1634..1952c0083 100644
--- a/src/core/hle/kernel/k_thread_local_page.cpp
+++ b/src/core/hle/kernel/k_thread_local_page.cpp
@@ -21,7 +21,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
// Allocate a new page.
KPageBuffer* page_buf = KPageBuffer::Allocate(kernel);
R_UNLESS(page_buf != nullptr, ResultOutOfMemory);
- auto page_buf_guard = SCOPE_GUARD({ KPageBuffer::Free(kernel, page_buf); });
+ auto page_buf_guard = SCOPE_GUARD {
+ KPageBuffer::Free(kernel, page_buf);
+ };
// Map the address in.
const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp
index cbb1b02bb..09295e8ad 100644
--- a/src/core/hle/kernel/k_transfer_memory.cpp
+++ b/src/core/hle/kernel/k_transfer_memory.cpp
@@ -24,7 +24,9 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size,
// Construct the page group, guarding to make sure our state is valid on exit.
m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
- auto pg_guard = SCOPE_GUARD({ m_page_group.reset(); });
+ auto pg_guard = SCOPE_GUARD {
+ m_page_group.reset();
+ };
// Lock the memory.
R_TRY(page_table.LockForTransferMemory(std::addressof(*m_page_group), addr, size,
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 34b25be66..9e5eaeec4 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -109,7 +109,9 @@ struct KernelCore::Impl {
void Shutdown() {
is_shutting_down.store(true, std::memory_order_relaxed);
- SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); });
+ SCOPE_EXIT {
+ is_shutting_down.store(false, std::memory_order_relaxed);
+ };
CloseServices();
@@ -1080,7 +1082,9 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
// Ensure that we don't hold onto any extra references.
- SCOPE_EXIT({ process->Close(); });
+ SCOPE_EXIT {
+ process->Close();
+ };
// Register the new process.
KProcess::Register(*this, process);
@@ -1108,7 +1112,9 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function
process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
// Ensure that we don't hold onto any extra references.
- SCOPE_EXIT({ process->Close(); });
+ SCOPE_EXIT {
+ process->Close();
+ };
// Register the new process.
KProcess::Register(*this, process);
@@ -1204,39 +1210,48 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
return *impl->hidbus_shared_mem;
}
-void KernelCore::SuspendApplication(bool suspended) {
+void KernelCore::SuspendEmulation(bool suspended) {
const bool should_suspend{exception_exited || suspended};
- const auto activity =
- should_suspend ? Svc::ProcessActivity::Paused : Svc::ProcessActivity::Runnable;
+ auto processes = GetProcessList();
- // Get the application process.
- KScopedAutoObject<KProcess> process = ApplicationProcess();
- if (process.IsNull()) {
- return;
+ for (auto& process : processes) {
+ KScopedLightLock ll{process->GetListLock()};
+
+ for (auto& thread : process->GetThreadList()) {
+ if (should_suspend) {
+ thread.RequestSuspend(SuspendType::System);
+ } else {
+ thread.Resume(SuspendType::System);
+ }
+ }
}
- // Set the new activity.
- process->SetActivity(activity);
+ if (!should_suspend) {
+ return;
+ }
// Wait for process execution to stop.
- bool must_wait{should_suspend};
-
- // KernelCore::SuspendApplication must be called from locked context,
- // or we could race another call to SetActivity, interfering with waiting.
- while (must_wait) {
+ // KernelCore::SuspendEmulation must be called from locked context,
+ // or we could race another call, interfering with waiting.
+ const auto TryWait = [&]() {
KScopedSchedulerLock sl{*this};
- // Assume that all threads have finished running.
- must_wait = false;
-
- for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
- if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
- process.GetPointerUnsafe()) {
- // A thread has not finished running yet.
- // Continue waiting.
- must_wait = true;
+ for (auto& process : processes) {
+ for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
+ if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
+ process.GetPointerUnsafe()) {
+ // A thread has not finished running yet.
+ // Continue waiting.
+ return false;
+ }
}
}
+
+ return true;
+ };
+
+ while (!TryWait()) {
+ // ...
}
}
@@ -1260,7 +1275,7 @@ bool KernelCore::IsShuttingDown() const {
void KernelCore::ExceptionalExitApplication() {
exception_exited = true;
- SuspendApplication(true);
+ SuspendEmulation(true);
}
void KernelCore::EnterSVCProfile() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 8ea5bed1c..57182c0c8 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -258,8 +258,8 @@ public:
/// Gets the shared memory object for HIDBus services.
const Kernel::KSharedMemory& GetHidBusSharedMem() const;
- /// Suspend/unsuspend application process.
- void SuspendApplication(bool suspend);
+ /// Suspend/unsuspend emulated processes.
+ void SuspendEmulation(bool suspend);
/// Exceptional exit application process.
void ExceptionalExitApplication();
diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp
index bae4cb0cd..7be2802f0 100644
--- a/src/core/hle/kernel/svc/svc_code_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_code_memory.cpp
@@ -45,7 +45,9 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t
KCodeMemory* code_mem = KCodeMemory::Create(kernel);
R_UNLESS(code_mem != nullptr, ResultOutOfResource);
- SCOPE_EXIT({ code_mem->Close(); });
+ SCOPE_EXIT {
+ code_mem->Close();
+ };
// Verify that the region is in range.
R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size),
diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp
index 42add9473..ac828320f 100644
--- a/src/core/hle/kernel/svc/svc_device_address_space.cpp
+++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp
@@ -28,7 +28,9 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_
// Create the device address space.
KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel());
R_UNLESS(das != nullptr, ResultOutOfResource);
- SCOPE_EXIT({ das->Close(); });
+ SCOPE_EXIT {
+ das->Close();
+ };
// Initialize the device address space.
R_TRY(das->Initialize(das_address, das_size));
diff --git a/src/core/hle/kernel/svc/svc_event.cpp b/src/core/hle/kernel/svc/svc_event.cpp
index 901202e6a..8e4beb396 100644
--- a/src/core/hle/kernel/svc/svc_event.cpp
+++ b/src/core/hle/kernel/svc/svc_event.cpp
@@ -72,10 +72,10 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
event_reservation.Commit();
// Ensure that we clean up the event (and its only references are handle table) on function end.
- SCOPE_EXIT({
+ SCOPE_EXIT {
event->GetReadableEvent().Close();
event->Close();
- });
+ };
// Register the event.
KEvent::Register(kernel, event);
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 85cc4f561..b619bd70a 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -129,11 +129,11 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes
}
// Ensure handles are closed when we're done.
- SCOPE_EXIT({
+ SCOPE_EXIT {
for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
- });
+ };
R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs,
num_handles, reply_target, timeout_ns));
@@ -208,10 +208,10 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
event_reservation.Commit();
// At end of scope, kill the standing references to the sub events.
- SCOPE_EXIT({
+ SCOPE_EXIT {
event->GetReadableEvent().Close();
event->Close();
- });
+ };
// Register the event.
KEvent::Register(system.Kernel(), event);
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index 737749f7d..9a22dadaf 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -68,10 +68,10 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
port->Initialize(max_sessions, is_light, name);
// Ensure that we clean up the port (and its only references are handle table) on function end.
- SCOPE_EXIT({
+ SCOPE_EXIT {
port->GetServerPort().Close();
port->GetClientPort().Close();
- });
+ };
// Register the port.
KPort::Register(kernel, port);
@@ -150,10 +150,10 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t
KPort::Register(system.Kernel(), port);
// Ensure that our only reference to the port is in the handle table when we're done.
- SCOPE_EXIT({
+ SCOPE_EXIT {
port->GetClientPort().Close();
port->GetServerPort().Close();
- });
+ };
// Register the handle in the table.
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp
index c8e820b6a..6f3972482 100644
--- a/src/core/hle/kernel/svc/svc_resource_limit.cpp
+++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp
@@ -18,7 +18,9 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
R_UNLESS(resource_limit != nullptr, ResultOutOfResource);
// Ensure we don't leak a reference to the limit.
- SCOPE_EXIT({ resource_limit->Close(); });
+ SCOPE_EXIT {
+ resource_limit->Close();
+ };
// Initialize the resource limit.
resource_limit->Initialize();
diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp
index 2f5905f32..b034d21d1 100644
--- a/src/core/hle/kernel/svc/svc_session.cpp
+++ b/src/core/hle/kernel/svc/svc_session.cpp
@@ -69,10 +69,10 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
// Ensure that we clean up the session (and its only references are handle table) on function
// end.
- SCOPE_EXIT({
+ SCOPE_EXIT {
session->GetClientSession().Close();
session->GetServerSession().Close();
- });
+ };
// Register the session.
T::Register(system.Kernel(), session);
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 6c79cfd8d..fb03908d7 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -78,11 +78,11 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
}
// Ensure handles are closed when we're done.
- SCOPE_EXIT({
+ SCOPE_EXIT {
for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
- });
+ };
// Convert the timeout from nanoseconds to ticks.
s64 timeout;
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 7681afa33..7517bb9d3 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -51,7 +51,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
// Create the thread.
KThread* thread = KThread::Create(kernel);
R_UNLESS(thread != nullptr, ResultOutOfResource)
- SCOPE_EXIT({ thread->Close(); });
+ SCOPE_EXIT {
+ thread->Close();
+ };
// Initialize the thread.
{
diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
index 671bca23f..2ea0d4421 100644
--- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
@@ -52,7 +52,9 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
R_UNLESS(trmem != nullptr, ResultOutOfResource);
// Ensure the only reference is in the handle table when we're done.
- SCOPE_EXIT({ trmem->Close(); });
+ SCOPE_EXIT {
+ trmem->Close();
+ };
// Ensure that the region is in range.
R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory);
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 29a10ad13..ee9795532 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -329,9 +329,8 @@ bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase&
/// Returns if the system is allowing user registrations or not
bool ProfileManager::CanSystemRegisterUser() const {
- return false; // TODO(ogniK): Games shouldn't have
- // access to user registration, when we
- // emulate qlaunch. Update this to dynamically change.
+ // TODO: Both games and applets can register users. Determine when this condition is not meet.
+ return true;
}
bool ProfileManager::RemoveUser(UUID uuid) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9dc710ba9..8c4e14f08 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -8,13 +8,13 @@
namespace Service::AM {
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
+void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService(
- "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
- server_manager->RegisterNamedService(
- "appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
+ server_manager->RegisterNamedService("appletAE",
+ std::make_shared<IAllSystemAppletProxiesService>(system));
+ server_manager->RegisterNamedService("appletOE",
+ std::make_shared<IApplicationProxyService>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 4a2d797bd..1afe253ae 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -7,12 +7,8 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
namespace Service::AM {
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
+void LoopProcess(Core::System& system);
} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
index 4f34d4811..ad602153e 100644
--- a/src/core/hle/service/am/applet.h
+++ b/src/core/hle/service/am/applet.h
@@ -14,10 +14,9 @@
#include "core/hle/service/am/am_types.h"
#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/am/display_layer_manager.h"
#include "core/hle/service/am/hid_registration.h"
-#include "core/hle/service/am/managed_layer_holder.h"
#include "core/hle/service/am/process.h"
-#include "core/hle/service/am/system_buffer_manager.h"
namespace Service::AM {
@@ -54,8 +53,7 @@ struct Applet {
HidRegistration hid_registration;
// vi state
- SystemBufferManager system_buffer_manager{};
- ManagedLayerHolder managed_layer_holder{};
+ DisplayLayerManager display_layer_manager{};
// Applet common functions
Result terminate_result{};
diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp
index 4d58c4db5..9057244a9 100644
--- a/src/core/hle/service/am/applet_data_broker.cpp
+++ b/src/core/hle/service/am/applet_data_broker.cpp
@@ -24,11 +24,11 @@ void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) {
Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) {
std::scoped_lock lk{m_lock};
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (m_data.empty()) {
m_event.Clear();
}
- });
+ };
R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel);
diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp
index 4c7266f89..2e109181d 100644
--- a/src/core/hle/service/am/applet_manager.cpp
+++ b/src/core/hle/service/am/applet_manager.cpp
@@ -35,6 +35,21 @@ AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system,
return applet->caller_applet_broker->GetInData();
}
+void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) {
+ const CommonArguments arguments{
+ .arguments_version = CommonArgumentVersion::Version3,
+ .size = CommonArgumentSize::Version3,
+ .library_version = 0,
+ .theme_color = ThemeColor::BasicBlack,
+ .play_startup_sound = true,
+ .system_tick = system.CoreTiming().GetClockTicks(),
+ };
+
+ std::vector<u8> argument_data(sizeof(arguments));
+ std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+ channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
+}
+
void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) {
const CommonArguments arguments{
.arguments_version = CommonArgumentVersion::Version3,
@@ -284,6 +299,9 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
// Starting from frontend, some applets require input data.
switch (applet->applet_id) {
+ case AppletId::QLaunch:
+ PushInShowQlaunch(m_system, InitializeFakeCallerApplet(m_system, applet));
+ break;
case AppletId::Cabinet:
PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet));
break;
diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp
new file mode 100644
index 000000000..85ff6fb88
--- /dev/null
+++ b/src/core/hle/service/am/display_layer_manager.cpp
@@ -0,0 +1,151 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/am/display_layer_manager.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_display_service.h"
+#include "core/hle/service/vi/manager_root_service.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
+#include "core/hle/service/vi/vi_results.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::AM {
+
+DisplayLayerManager::DisplayLayerManager() = default;
+DisplayLayerManager::~DisplayLayerManager() {
+ this->Finalize();
+}
+
+void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process,
+ AppletId applet_id, LibraryAppletMode mode) {
+ R_ASSERT(system.ServiceManager()
+ .GetService<VI::IManagerRootService>("vi:m", true)
+ ->GetDisplayService(&m_display_service, VI::Policy::Compositor));
+ R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service));
+
+ m_process = process;
+ m_system_shared_buffer_id = 0;
+ m_system_shared_layer_id = 0;
+ m_applet_id = applet_id;
+ m_buffer_sharing_enabled = false;
+ m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
+ mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
+}
+
+void DisplayLayerManager::Finalize() {
+ if (!m_manager_display_service) {
+ return;
+ }
+
+ // Clean up managed layers.
+ for (const auto& layer : m_managed_display_layers) {
+ m_manager_display_service->DestroyManagedLayer(layer);
+ }
+
+ for (const auto& layer : m_managed_display_recording_layers) {
+ m_manager_display_service->DestroyManagedLayer(layer);
+ }
+
+ // Clean up shared layers.
+ if (m_buffer_sharing_enabled) {
+ m_manager_display_service->DestroySharedLayerSession(m_process);
+ }
+
+ m_manager_display_service = nullptr;
+ m_display_service = nullptr;
+}
+
+Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+
+ // TODO(Subv): Find out how AM determines the display to use, for now just
+ // create the layer in the Default display.
+ u64 display_id;
+ R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
+ R_TRY(m_manager_display_service->CreateManagedLayer(
+ out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
+
+ m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
+ m_managed_display_layers.emplace(*out_layer_id);
+
+ R_SUCCEED();
+}
+
+Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id,
+ u64* out_recording_layer_id) {
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+
+ // TODO(Subv): Find out how AM determines the display to use, for now just
+ // create the layer in the Default display.
+ // This calls nn::vi::CreateRecordingLayer() which creates another layer.
+ // Currently we do not support more than 1 layer per display, output 1 layer id for now.
+ // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
+ // side effects.
+ *out_recording_layer_id = 0;
+ R_RETURN(this->CreateManagedDisplayLayer(out_layer_id));
+}
+
+Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
+ // Succeed if already enabled.
+ R_SUCCEED_IF(m_buffer_sharing_enabled);
+
+ // Ensure we can access shared layers.
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+ R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied);
+
+ // Create the shared layer.
+ u64 display_id;
+ R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
+ R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id,
+ &m_system_shared_layer_id, display_id,
+ m_blending_enabled));
+
+ // We succeeded, so set up remaining state.
+ m_buffer_sharing_enabled = true;
+ m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
+ R_SUCCEED();
+}
+
+Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
+ u64* out_system_shared_layer_id) {
+ R_TRY(this->IsSystemBufferSharingEnabled());
+
+ *out_system_shared_buffer_id = m_system_shared_buffer_id;
+ *out_system_shared_layer_id = m_system_shared_layer_id;
+
+ R_SUCCEED();
+}
+
+void DisplayLayerManager::SetWindowVisibility(bool visible) {
+ if (m_visible == visible) {
+ return;
+ }
+
+ m_visible = visible;
+
+ if (m_manager_display_service) {
+ if (m_system_shared_layer_id) {
+ m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
+ }
+
+ for (const auto layer_id : m_managed_display_layers) {
+ m_manager_display_service->SetLayerVisibility(m_visible, layer_id);
+ }
+ }
+}
+
+bool DisplayLayerManager::GetWindowVisibility() const {
+ return m_visible;
+}
+
+Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
+ s32* out_fbshare_layer_index) {
+ R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
+ R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
+ out_was_written, out_fbshare_layer_index));
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h
new file mode 100644
index 000000000..a66509c04
--- /dev/null
+++ b/src/core/hle/service/am/display_layer_manager.h
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <set>
+
+#include "common/common_types.h"
+#include "core/hle/result.h"
+#include "core/hle/service/am/am_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KProcess;
+}
+
+namespace Service::VI {
+class IApplicationDisplayService;
+class IManagerDisplayService;
+} // namespace Service::VI
+
+namespace Service::AM {
+
+class DisplayLayerManager {
+public:
+ explicit DisplayLayerManager();
+ ~DisplayLayerManager();
+
+ void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id,
+ LibraryAppletMode mode);
+ void Finalize();
+
+ Result CreateManagedDisplayLayer(u64* out_layer_id);
+ Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id);
+
+ Result IsSystemBufferSharingEnabled();
+ Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
+ u64* out_system_shared_layer_id);
+
+ void SetWindowVisibility(bool visible);
+ bool GetWindowVisibility() const;
+
+ Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
+
+private:
+ Kernel::KProcess* m_process{};
+ std::shared_ptr<VI::IApplicationDisplayService> m_display_service{};
+ std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{};
+ std::set<u64> m_managed_display_layers{};
+ std::set<u64> m_managed_display_recording_layers{};
+ u64 m_system_shared_buffer_id{};
+ u64 m_system_shared_layer_id{};
+ AppletId m_applet_id{};
+ bool m_buffer_sharing_enabled{};
+ bool m_blending_enabled{};
+ bool m_visible{true};
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/frontend/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp
index bb60260b4..835c20c4e 100644
--- a/src/core/hle/service/am/frontend/applet_web_browser.cpp
+++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp
@@ -22,7 +22,7 @@
#include "core/hle/service/am/frontend/applet_web_browser.h"
#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
+#include "core/hle/service/ns/platform_service_manager.h"
#include "core/loader/loader.h"
namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp
index 46e6c0111..0412c215d 100644
--- a/src/core/hle/service/am/library_applet_storage.cpp
+++ b/src/core/hle/service/am/library_applet_storage.cpp
@@ -70,7 +70,7 @@ public:
Result Read(s64 offset, void* buffer, size_t size) override {
R_TRY(ValidateOffset(offset, size, m_size));
- m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size);
+ m_memory.ReadBlock(m_trmem->GetSourceAddress() + offset, buffer, size);
R_SUCCEED();
}
@@ -79,7 +79,7 @@ public:
R_UNLESS(m_is_writable, ResultUnknown);
R_TRY(ValidateOffset(offset, size, m_size));
- m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size);
+ m_memory.WriteBlock(m_trmem->GetSourceAddress() + offset, buffer, size);
R_SUCCEED();
}
diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp
deleted file mode 100644
index 61eb8641a..000000000
--- a/src/core/hle/service/am/managed_layer_holder.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/managed_layer_holder.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-
-namespace Service::AM {
-
-ManagedLayerHolder::ManagedLayerHolder() = default;
-ManagedLayerHolder::~ManagedLayerHolder() {
- if (!m_nvnflinger) {
- return;
- }
-
- for (const auto& layer : m_managed_display_layers) {
- m_nvnflinger->DestroyLayer(layer);
- }
-
- for (const auto& layer : m_managed_display_recording_layers) {
- m_nvnflinger->DestroyLayer(layer);
- }
-
- m_nvnflinger = nullptr;
-}
-
-void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) {
- m_nvnflinger = nvnflinger;
-}
-
-void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) {
- // TODO(Subv): Find out how AM determines the display to use, for now just
- // create the layer in the Default display.
- const auto display_id = m_nvnflinger->OpenDisplay("Default");
- const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
-
- m_managed_display_layers.emplace(*layer_id);
-
- *out_layer = *layer_id;
-}
-
-void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer,
- u64* out_recording_layer) {
- // TODO(Subv): Find out how AM determines the display to use, for now just
- // create the layer in the Default display.
- // This calls nn::vi::CreateRecordingLayer() which creates another layer.
- // Currently we do not support more than 1 layer per display, output 1 layer id for now.
- // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
- // side effects.
- // TODO: Support multiple layers
- const auto display_id = m_nvnflinger->OpenDisplay("Default");
- const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
-
- m_managed_display_layers.emplace(*layer_id);
-
- *out_layer = *layer_id;
- *out_recording_layer = 0;
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h
deleted file mode 100644
index f7fe03f24..000000000
--- a/src/core/hle/service/am/managed_layer_holder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <set>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
-namespace Service::AM {
-
-class ManagedLayerHolder {
-public:
- ManagedLayerHolder();
- ~ManagedLayerHolder();
-
- void Initialize(Nvnflinger::Nvnflinger* nvnflinger);
- void CreateManagedDisplayLayer(u64* out_layer);
- void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer);
-
-private:
- Nvnflinger::Nvnflinger* m_nvnflinger{};
- std::set<u64> m_managed_display_layers{};
- std::set<u64> m_managed_display_recording_layers{};
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp
index 992c50713..388d2045c 100644
--- a/src/core/hle/service/am/process.cpp
+++ b/src/core/hle/service/am/process.cpp
@@ -68,7 +68,9 @@ bool Process::Initialize(u64 program_id, u8 minimum_key_generation, u8 maximum_k
Kernel::KProcess::Register(m_system.Kernel(), process);
// On exit, ensure we free the additional reference to the process.
- SCOPE_EXIT({ process->Close(); });
+ SCOPE_EXIT {
+ process->Close();
+ };
// Insert process modules into memory.
const auto [load_result, load_parameters] = app_loader->Load(*process, m_system);
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 eebd90ba2..21747783a 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
@@ -10,9 +10,8 @@
namespace Service::AM {
-IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} {
+IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_)
+ : ServiceFramework{system_, "appletAE"} {
// clang-format off
static const FunctionInfo functions[] = {
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
@@ -37,8 +36,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
- *out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
- system, applet, process_handle.Get(), m_nvnflinger);
+ *out_system_applet_proxy =
+ std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get());
R_SUCCEED();
} else {
UNIMPLEMENTED();
@@ -53,8 +52,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
- *out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
- system, applet, process_handle.Get(), m_nvnflinger);
+ *out_library_applet_proxy =
+ std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get());
R_SUCCEED();
} else {
UNIMPLEMENTED();
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 38b1ca2ea..0e2dcb86d 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
@@ -8,10 +8,6 @@
namespace Service {
-namespace Nvnflinger {
-class Nvnflinger;
-}
-
namespace AM {
struct Applet;
@@ -22,8 +18,7 @@ class ISystemAppletProxy;
class IAllSystemAppletProxiesService final
: public ServiceFramework<IAllSystemAppletProxiesService> {
public:
- explicit IAllSystemAppletProxiesService(Core::System& system_,
- Nvnflinger::Nvnflinger& nvnflinger);
+ explicit IAllSystemAppletProxiesService(Core::System& system_);
~IAllSystemAppletProxiesService() override;
private:
@@ -40,7 +35,6 @@ private:
private:
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
- Nvnflinger::Nvnflinger& m_nvnflinger;
};
} // namespace AM
diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp
index b788fddd4..cb53b07e0 100644
--- a/src/core/hle/service/am/service/application_functions.cpp
+++ b/src/core/hle/service/am/service/application_functions.cpp
@@ -15,7 +15,9 @@
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/save_data_controller.h"
-#include "core/hle/service/ns/ns.h"
+#include "core/hle/service/glue/glue_manager.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
#include "core/hle/service/sm/sm.h"
namespace Service::AM {
@@ -40,7 +42,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
{26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
{27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
{28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
- {29, nullptr, "GetCacheStorageMax"},
+ {29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"},
{30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
{31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
{32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
@@ -162,11 +164,13 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
// Call IApplicationManagerInterface implementation.
auto& service_manager = system.ServiceManager();
- auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
+ auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
+
+ std::shared_ptr<NS::IApplicationManagerInterface> app_man;
+ R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
// Get desired application language
- u8 desired_language{};
+ NS::ApplicationLanguage desired_language{};
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
// Convert to settings language code.
@@ -267,6 +271,22 @@ Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
R_SUCCEED();
}
+Result IApplicationFunctions::GetCacheStorageMax(Out<u32> out_cache_storage_index_max,
+ Out<u64> out_max_journal_size) {
+ LOG_DEBUG(Service_AM, "called");
+
+ std::vector<u8> nacp;
+ R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id));
+
+ auto raw_nacp = std::make_unique<FileSys::RawNACP>();
+ std::memcpy(raw_nacp.get(), nacp.data(), std::min(sizeof(*raw_nacp), nacp.size()));
+
+ *out_cache_storage_index_max = static_cast<u32>(raw_nacp->cache_storage_max_index);
+ *out_max_journal_size = static_cast<u64>(raw_nacp->cache_storage_data_and_journal_max_size);
+
+ R_SUCCEED();
+}
+
Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) {
LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h
index 3548202f8..10025a152 100644
--- a/src/core/hle/service/am/service/application_functions.h
+++ b/src/core/hle/service/am/service/application_functions.h
@@ -40,6 +40,7 @@ private:
Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index,
u64 normal_size, u64 journal_size);
Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size);
+ Result GetCacheStorageMax(Out<u32> out_cache_storage_index_max, Out<u64> out_max_journal_size);
Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused);
Result EndBlockingHomeButtonShortAndLongPressed();
Result BeginBlockingHomeButton(s64 timeout_ns);
diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp
index 776f4552b..19d6a3b89 100644
--- a/src/core/hle/service/am/service/application_proxy.cpp
+++ b/src/core/hle/service/am/service/application_proxy.cpp
@@ -17,9 +17,9 @@
namespace Service::AM {
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "IApplicationProxy"},
- m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
+ Kernel::KProcess* process)
+ : ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{
+ std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
@@ -77,8 +77,7 @@ Result IApplicationProxy::GetWindowController(
Result IApplicationProxy::GetSelfController(
Out<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
R_SUCCEED();
}
diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h
index 1ebc593ba..6da350df7 100644
--- a/src/core/hle/service/am/service/application_proxy.h
+++ b/src/core/hle/service/am/service/application_proxy.h
@@ -22,7 +22,7 @@ class IWindowController;
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
public:
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~IApplicationProxy();
private:
@@ -40,7 +40,6 @@ private:
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> m_applet;
};
diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp
index 36d4478df..fd66e77b9 100644
--- a/src/core/hle/service/am/service/application_proxy_service.cpp
+++ b/src/core/hle/service/am/service/application_proxy_service.cpp
@@ -10,9 +10,8 @@
namespace Service::AM {
-IApplicationProxyService::IApplicationProxyService(Core::System& system_,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} {
+IApplicationProxyService::IApplicationProxyService(Core::System& system_)
+ : ServiceFramework{system_, "appletOE"} {
static const FunctionInfo functions[] = {
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
};
@@ -28,7 +27,7 @@ Result IApplicationProxyService::OpenApplicationProxy(
if (const auto applet = this->GetAppletFromProcessId(pid)) {
*out_application_proxy =
- std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger);
+ std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());
R_SUCCEED();
} else {
UNIMPLEMENTED();
diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h
index 1c1d32d0b..8efafa31a 100644
--- a/src/core/hle/service/am/service/application_proxy_service.h
+++ b/src/core/hle/service/am/service/application_proxy_service.h
@@ -8,10 +8,6 @@
namespace Service {
-namespace Nvnflinger {
-class Nvnflinger;
-}
-
namespace AM {
struct Applet;
@@ -19,7 +15,7 @@ class IApplicationProxy;
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
public:
- explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
+ explicit IApplicationProxyService(Core::System& system_);
~IApplicationProxyService() override;
private:
@@ -28,7 +24,6 @@ private:
private:
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
- Nvnflinger::Nvnflinger& m_nvnflinger;
};
} // namespace AM
diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp
index 249c73dfb..ed71f9093 100644
--- a/src/core/hle/service/am/service/display_controller.cpp
+++ b/src/core/hle/service/am/service/display_controller.cpp
@@ -69,7 +69,7 @@ Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_i
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_WARNING(Service_AM, "(STUBBED) called");
- R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_fbshare_layer_index));
}
@@ -81,7 +81,7 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_WARNING(Service_AM, "(STUBBED) called");
- R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_fbshare_layer_index));
}
@@ -93,7 +93,7 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_WARNING(Service_AM, "(STUBBED) called");
- R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_fbshare_layer_index));
}
diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp
index 166637d60..c97358d81 100644
--- a/src/core/hle/service/am/service/library_applet_creator.cpp
+++ b/src/core/hle/service/am/service/library_applet_creator.cpp
@@ -135,7 +135,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
case LibraryAppletMode::AllForegroundInitiallyHidden:
applet->hid_registration.EnableAppletToGetInput(false);
applet->focus_state = FocusState::NotInFocus;
- applet->system_buffer_manager.SetWindowVisibility(false);
+ applet->display_layer_manager.SetWindowVisibility(false);
applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
break;
}
diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp
index bcb44a71c..58e709347 100644
--- a/src/core/hle/service/am/service/library_applet_proxy.cpp
+++ b/src/core/hle/service/am/service/library_applet_proxy.cpp
@@ -19,10 +19,9 @@
namespace Service::AM {
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "ILibraryAppletProxy"},
- m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
+ Kernel::KProcess* process)
+ : ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{
+ std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
@@ -83,8 +82,7 @@ Result ILibraryAppletProxy::GetWindowController(
Result ILibraryAppletProxy::GetSelfController(
Out<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
R_SUCCEED();
}
diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h
index 23e64e295..7d0714b85 100644
--- a/src/core/hle/service/am/service/library_applet_proxy.h
+++ b/src/core/hle/service/am/service/library_applet_proxy.h
@@ -25,7 +25,7 @@ class IWindowController;
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
public:
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~ILibraryAppletProxy();
private:
@@ -47,7 +47,6 @@ private:
Result GetGlobalStateController(
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> m_applet;
};
diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp
index 7a3a86e88..330eb26f0 100644
--- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp
@@ -14,7 +14,8 @@
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/glue_manager.h"
-#include "core/hle/service/ns/ns.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
#include "core/hle/service/sm/sm.h"
namespace Service::AM {
@@ -256,11 +257,13 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
// Call IApplicationManagerInterface implementation.
auto& service_manager = system.ServiceManager();
- auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
+ auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
+
+ std::shared_ptr<NS::IApplicationManagerInterface> app_man;
+ R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
// Get desired application language
- u8 desired_language{};
+ NS::ApplicationLanguage desired_language{};
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
// Convert to settings language code.
@@ -284,17 +287,17 @@ Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_applicat
}
Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
- Out<bool> out_no_users_available, Out<s32> out_users_count,
+ Out<bool> out_can_select_any_user, Out<s32> out_users_count,
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) {
const Service::Account::ProfileManager manager{};
- *out_no_users_available = true;
+ *out_can_select_any_user = false;
*out_users_count = -1;
LOG_INFO(Service_AM, "called");
if (manager.GetUserCount() > 0) {
- *out_no_users_available = false;
+ *out_can_select_any_user = true;
*out_users_count = static_cast<s32>(manager.GetUserCount());
const auto users = manager.GetAllUsers();
diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.h b/src/core/hle/service/am/service/library_applet_self_accessor.h
index a9743569f..3e60393c2 100644
--- a/src/core/hle/service/am/service/library_applet_self_accessor.h
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.h
@@ -71,7 +71,7 @@ private:
ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context);
Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
Result GetCurrentApplicationId(Out<u64> out_application_id);
- Result GetMainAppletAvailableUsers(Out<bool> out_no_users_available, Out<s32> out_users_count,
+ Result GetMainAppletAvailableUsers(Out<bool> out_can_select_any_user, Out<s32> out_users_count,
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users);
Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually);
Result Cmd160(Out<u64> out_unknown0);
diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp
index 5c4c13de1..06314407c 100644
--- a/src/core/hle/service/am/service/self_controller.cpp
+++ b/src/core/hle/service/am/service/self_controller.cpp
@@ -15,9 +15,9 @@
namespace Service::AM {
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "ISelfController"},
- m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
+ Kernel::KProcess* process)
+ : ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{
+ std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISelfController::Exit>, "Exit"},
@@ -72,9 +72,16 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
// clang-format on
RegisterHandlers(functions);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->display_layer_manager.Initialize(system, m_process, m_applet->applet_id,
+ m_applet->library_applet_mode);
}
-ISelfController::~ISelfController() = default;
+ISelfController::~ISelfController() {
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->display_layer_manager.Finalize();
+}
Result ISelfController::Exit() {
LOG_DEBUG(Service_AM, "called");
@@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation(
Result ISelfController::IsSystemBufferSharingEnabled() {
LOG_INFO(Service_AM, "called");
- R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize(
- &m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode));
- R_THROW(VI::ResultOperationFailed);
+
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled());
}
Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- R_TRY(this->IsSystemBufferSharingEnabled());
+ LOG_INFO(Service_AM, "called");
u64 layer_id;
- m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id);
- R_SUCCEED();
+
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id));
}
Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) {
- LOG_INFO(Service_AM, "(STUBBED) called");
-
- R_TRY(this->IsSystemBufferSharingEnabled());
+ LOG_INFO(Service_AM, "called");
- m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id);
- R_SUCCEED();
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(
+ m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id));
}
Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) {
LOG_INFO(Service_AM, "called");
- m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
- m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id);
-
- R_SUCCEED();
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id));
}
Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
Out<u64> out_recording_layer_id) {
LOG_WARNING(Service_AM, "(STUBBED) called");
- m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
- m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id,
- out_recording_layer_id);
-
- R_SUCCEED();
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(m_applet->display_layer_manager.CreateManagedDisplaySeparableLayer(
+ out_layer_id, out_recording_layer_id));
}
Result ISelfController::SetHandlesRequestToDisplay(bool enable) {
diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h
index 01fa381a3..eca083cfe 100644
--- a/src/core/hle/service/am/service/self_controller.h
+++ b/src/core/hle/service/am/service/self_controller.h
@@ -23,7 +23,7 @@ struct Applet;
class ISelfController final : public ServiceFramework<ISelfController> {
public:
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~ISelfController() override;
private:
@@ -64,7 +64,6 @@ private:
Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
Result SetRecordVolumeMuted(bool muted);
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> m_applet;
};
diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp
index 5ec509d2e..d1871ef9b 100644
--- a/src/core/hle/service/am/service/system_applet_proxy.cpp
+++ b/src/core/hle/service/am/service/system_applet_proxy.cpp
@@ -19,10 +19,9 @@
namespace Service::AM {
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "ISystemAppletProxy"},
- m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
+ Kernel::KProcess* process)
+ : ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{
+ std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
@@ -83,8 +82,7 @@ Result ISystemAppletProxy::GetWindowController(
Result ISystemAppletProxy::GetSelfController(
Out<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
R_SUCCEED();
}
diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h
index 3d5040315..67cd50e03 100644
--- a/src/core/hle/service/am/service/system_applet_proxy.h
+++ b/src/core/hle/service/am/service/system_applet_proxy.h
@@ -25,7 +25,7 @@ class IWindowController;
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
public:
explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~ISystemAppletProxy();
private:
@@ -46,7 +46,6 @@ private:
Result GetGlobalStateController(
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> m_applet;
};
diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp
index b874ecb91..99a4f50a2 100644
--- a/src/core/hle/service/am/service/window_controller.cpp
+++ b/src/core/hle/service/am/service/window_controller.cpp
@@ -63,7 +63,7 @@ Result IWindowController::RejectToChangeIntoBackground() {
}
Result IWindowController::SetAppletWindowVisibility(bool visible) {
- m_applet->system_buffer_manager.SetWindowVisibility(visible);
+ m_applet->display_layer_manager.SetWindowVisibility(visible);
m_applet->hid_registration.EnableAppletToGetInput(visible);
if (visible) {
diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp
deleted file mode 100644
index 48923fe41..000000000
--- a/src/core/hle/service/am/system_buffer_manager.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/system_buffer_manager.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/vi/vi_results.h"
-
-namespace Service::AM {
-
-SystemBufferManager::SystemBufferManager() = default;
-
-SystemBufferManager::~SystemBufferManager() {
- if (!m_nvnflinger) {
- return;
- }
-
- // Clean up shared layers.
- if (m_buffer_sharing_enabled) {
- m_nvnflinger->GetSystemBufferManager().Finalize(m_process);
- }
-}
-
-bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process,
- AppletId applet_id, LibraryAppletMode mode) {
- if (m_nvnflinger) {
- return m_buffer_sharing_enabled;
- }
-
- m_process = process;
- m_nvnflinger = nvnflinger;
- m_buffer_sharing_enabled = false;
- m_system_shared_buffer_id = 0;
- m_system_shared_layer_id = 0;
-
- if (applet_id <= AppletId::Application) {
- return false;
- }
-
- Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None;
- if (mode == LibraryAppletMode::PartialForeground ||
- mode == LibraryAppletMode::PartialForegroundIndirectDisplay) {
- blending = Nvnflinger::LayerBlending::Coverage;
- }
-
- const auto display_id = m_nvnflinger->OpenDisplay("Default").value();
- const auto res = m_nvnflinger->GetSystemBufferManager().Initialize(
- m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending);
-
- if (res.IsSuccess()) {
- m_buffer_sharing_enabled = true;
- m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible);
- }
-
- return m_buffer_sharing_enabled;
-}
-
-void SystemBufferManager::SetWindowVisibility(bool visible) {
- if (m_visible == visible) {
- return;
- }
-
- m_visible = visible;
-
- if (m_nvnflinger) {
- m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible);
- }
-}
-
-Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written,
- s32* out_fbshare_layer_index) {
- if (!m_buffer_sharing_enabled) {
- return VI::ResultPermissionDenied;
- }
-
- return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written,
- out_fbshare_layer_index);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h
deleted file mode 100644
index 0690f68b6..000000000
--- a/src/core/hle/service/am/system_buffer_manager.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <set>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-
-#include "core/hle/service/am/am_types.h"
-
-namespace Kernel {
-class KProcess;
-}
-
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
-union Result;
-
-namespace Service::AM {
-
-class SystemBufferManager {
-public:
- SystemBufferManager();
- ~SystemBufferManager();
-
- bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id,
- LibraryAppletMode mode);
-
- void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
- u64* out_system_shared_layer_id) {
- *out_system_shared_buffer_id = m_system_shared_buffer_id;
- *out_system_shared_layer_id = m_system_shared_layer_id;
- }
-
- void SetWindowVisibility(bool visible);
-
- Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
-
-private:
- Kernel::KProcess* m_process{};
- Nvnflinger::Nvnflinger* m_nvnflinger{};
- bool m_buffer_sharing_enabled{};
- bool m_visible{true};
- u64 m_system_shared_buffer_id{};
- u64 m_system_shared_layer_id{};
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
deleted file mode 100644
index cf4bb4034..000000000
--- a/src/core/hle/service/audio/audctl.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/service/audio/audctl.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/set/system_settings_server.h"
-#include "core/hle/service/sm/sm.h"
-
-namespace Service::Audio {
-
-AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetTargetVolume"},
- {1, nullptr, "SetTargetVolume"},
- {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"},
- {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"},
- {4, nullptr, "IsTargetMute"},
- {5, nullptr, "SetTargetMute"},
- {6, nullptr, "IsTargetConnected"},
- {7, nullptr, "SetDefaultTarget"},
- {8, nullptr, "GetDefaultTarget"},
- {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
- {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
- {11, nullptr, "SetForceMutePolicy"},
- {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
- {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
- {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
- {15, nullptr, "SetOutputTarget"},
- {16, nullptr, "SetInputTargetForceEnabled"},
- {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
- {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
- {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
- {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
- {21, nullptr, "GetAudioOutputTargetForPlayReport"},
- {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
- {23, nullptr, "SetSystemOutputMasterVolume"},
- {24, nullptr, "GetSystemOutputMasterVolume"},
- {25, nullptr, "GetAudioVolumeDataForPlayReport"},
- {26, nullptr, "UpdateHeadphoneSettings"},
- {27, nullptr, "SetVolumeMappingTableForDev"},
- {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
- {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
- {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
- {32, nullptr, "GetActiveOutputTarget"},
- {33, nullptr, "GetTargetDeviceInfo"},
- {34, nullptr, "AcquireTargetNotification"},
- {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
- {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
- {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
- {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
- {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
- {40, nullptr, "GetSystemInformationForDebug"},
- {41, nullptr, "SetVolumeButtonLongPressTime"},
- {42, nullptr, "SetNativeVolumeForDebug"},
- {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
- {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
- {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
- {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
- {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
- {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
- {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
- {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
- {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
- {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- m_set_sys =
- system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
-}
-
-AudCtl::~AudCtl() = default;
-
-void AudCtl::GetTargetVolumeMin(HLERequestContext& ctx) {
- LOG_DEBUG(Audio, "called.");
-
- // This service function is currently hardcoded on the
- // actual console to this value (as of 8.0.0).
- constexpr s32 target_min_volume = 0;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(target_min_volume);
-}
-
-void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
- LOG_DEBUG(Audio, "called.");
-
- // This service function is currently hardcoded on the
- // actual console to this value (as of 8.0.0).
- constexpr s32 target_max_volume = 15;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(target_max_volume);
-}
-
-void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
-
- Set::AudioOutputMode output_mode{};
- const auto result = m_set_sys->GetAudioOutputMode(&output_mode, target);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.PushEnum(output_mode);
-}
-
-void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
-
- const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(ForceMutePolicy::Disable);
-}
-
-void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
-
- LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(Set::AudioOutputMode::ch_7_1);
-}
-
-void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(HeadphoneOutputLevelMode::Normal);
-}
-
-void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
-
- LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
- is_speaker_auto_mute_enabled);
-
- const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
- bool is_speaker_auto_mute_enabled{};
- const auto result = m_set_sys->GetSpeakerAutoMuteFlag(&is_speaker_auto_mute_enabled);
-
- LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
- is_speaker_auto_mute_enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push<u8>(is_speaker_auto_mute_enabled);
-}
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
deleted file mode 100644
index 4c90ead70..000000000
--- a/src/core/hle/service/audio/audctl.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Set {
-class ISystemSettingsServer;
-}
-
-namespace Service::Audio {
-
-class AudCtl final : public ServiceFramework<AudCtl> {
-public:
- explicit AudCtl(Core::System& system_);
- ~AudCtl() override;
-
-private:
- enum class ForceMutePolicy {
- Disable,
- SpeakerMuteOnHeadphoneUnplugged,
- };
-
- enum class HeadphoneOutputLevelMode {
- Normal,
- HighPower,
- };
-
- void GetTargetVolumeMin(HLERequestContext& ctx);
- void GetTargetVolumeMax(HLERequestContext& ctx);
- void GetAudioOutputMode(HLERequestContext& ctx);
- void SetAudioOutputMode(HLERequestContext& ctx);
- void GetForceMutePolicy(HLERequestContext& ctx);
- void GetOutputModeSetting(HLERequestContext& ctx);
- void SetOutputModeSetting(HLERequestContext& ctx);
- void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
- void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
- void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
- void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
- void AcquireTargetNotification(HLERequestContext& ctx);
-
- std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
-};
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index dccd16309..44af030eb 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
-#include "core/hle/service/audio/audctl.h"
#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h"
+#include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/audio/audout_u.h"
#include "core/hle/service/audio/audrec_a.h"
#include "core/hle/service/audio/audrec_u.h"
@@ -18,7 +18,7 @@ namespace Service::Audio {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system));
+ server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp
new file mode 100644
index 000000000..a6da66d0f
--- /dev/null
+++ b/src/core/hle/service/audio/audio_controller.cpp
@@ -0,0 +1,174 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/service/audio/audio_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/set/system_settings_server.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Audio {
+
+IAudioController::IAudioController(Core::System& system_)
+ : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetTargetVolume"},
+ {1, nullptr, "SetTargetVolume"},
+ {2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
+ {3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
+ {4, nullptr, "IsTargetMute"},
+ {5, nullptr, "SetTargetMute"},
+ {6, nullptr, "IsTargetConnected"},
+ {7, nullptr, "SetDefaultTarget"},
+ {8, nullptr, "GetDefaultTarget"},
+ {9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
+ {10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
+ {11, nullptr, "SetForceMutePolicy"},
+ {12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
+ {13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
+ {14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
+ {15, nullptr, "SetOutputTarget"},
+ {16, nullptr, "SetInputTargetForceEnabled"},
+ {17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
+ {18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
+ {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
+ {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
+ {21, nullptr, "GetAudioOutputTargetForPlayReport"},
+ {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
+ {23, nullptr, "SetSystemOutputMasterVolume"},
+ {24, nullptr, "GetSystemOutputMasterVolume"},
+ {25, nullptr, "GetAudioVolumeDataForPlayReport"},
+ {26, nullptr, "UpdateHeadphoneSettings"},
+ {27, nullptr, "SetVolumeMappingTableForDev"},
+ {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
+ {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
+ {30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
+ {31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
+ {32, nullptr, "GetActiveOutputTarget"},
+ {33, nullptr, "GetTargetDeviceInfo"},
+ {34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
+ {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
+ {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
+ {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
+ {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
+ {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
+ {40, nullptr, "GetSystemInformationForDebug"},
+ {41, nullptr, "SetVolumeButtonLongPressTime"},
+ {42, nullptr, "SetNativeVolumeForDebug"},
+ {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
+ {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
+ {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
+ {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
+ {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
+ {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
+ {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
+ {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
+ {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
+ {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
+ {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ m_set_sys =
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
+ notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
+}
+
+IAudioController::~IAudioController() {
+ service_context.CloseEvent(notification_event);
+};
+
+Result IAudioController::GetTargetVolumeMin(Out<s32> out_target_min_volume) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 8.0.0).
+ *out_target_min_volume = 0;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetTargetVolumeMax(Out<s32> out_target_max_volume) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 8.0.0).
+ *out_target_max_volume = 15;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target) {
+ const auto result = m_set_sys->GetAudioOutputMode(out_output_mode, target);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
+ R_RETURN(result);
+}
+
+Result IAudioController::SetAudioOutputMode(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode) {
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ R_RETURN(m_set_sys->SetAudioOutputMode(target, output_mode));
+}
+
+Result IAudioController::GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy) {
+ LOG_WARNING(Audio, "(STUBBED) called");
+
+ // Removed on FW 13.2.1+
+ *out_mute_policy = ForceMutePolicy::Disable;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target) {
+ LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
+
+ *out_output_mode = Set::AudioOutputMode::ch_7_1;
+ R_SUCCEED();
+}
+
+Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode) {
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+ R_SUCCEED();
+}
+
+Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) {
+ LOG_WARNING(Audio, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IAudioController::GetHeadphoneOutputLevelMode(
+ Out<HeadphoneOutputLevelMode> out_output_level_mode) {
+ LOG_INFO(Audio, "called");
+
+ *out_output_level_mode = HeadphoneOutputLevelMode::Normal;
+ R_SUCCEED();
+}
+
+Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
+ LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);
+
+ R_RETURN(m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled));
+}
+
+Result IAudioController::IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled) {
+ const auto result = m_set_sys->GetSpeakerAutoMuteFlag(out_is_speaker_auto_mute_enabled);
+
+ LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", *out_is_speaker_auto_mute_enabled);
+ R_RETURN(result);
+}
+
+Result IAudioController::AcquireTargetNotification(
+ OutCopyHandle<Kernel::KReadableEvent> out_notification_event) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ *out_notification_event = &notification_event->GetReadableEvent();
+ 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
new file mode 100644
index 000000000..9e8514373
--- /dev/null
+++ b/src/core/hle/service/audio/audio_controller.h
@@ -0,0 +1,58 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Set {
+class ISystemSettingsServer;
+}
+
+namespace Service::Audio {
+
+class IAudioController final : public ServiceFramework<IAudioController> {
+public:
+ explicit IAudioController(Core::System& system_);
+ ~IAudioController() override;
+
+private:
+ enum class ForceMutePolicy {
+ Disable,
+ SpeakerMuteOnHeadphoneUnplugged,
+ };
+
+ enum class HeadphoneOutputLevelMode {
+ Normal,
+ HighPower,
+ };
+
+ Result GetTargetVolumeMin(Out<s32> out_target_min_volume);
+ Result GetTargetVolumeMax(Out<s32> out_target_max_volume);
+ Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target);
+ Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode);
+ Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy);
+ Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target);
+ Result SetOutputModeSetting(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode);
+ Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
+ Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
+ 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);
+
+ KernelHelpers::ServiceContext service_context;
+
+ Kernel::KEvent* notification_event;
+ std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 47ff072c5..52228b830 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -16,7 +16,7 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetAlbumFileCount"},
- {1, nullptr, "GetAlbumFileList"},
+ {1, C<&IAlbumAccessorService::GetAlbumFileList>, "GetAlbumFileList"},
{2, nullptr, "LoadAlbumFile"},
{3, C<&IAlbumAccessorService::DeleteAlbumFile>, "DeleteAlbumFile"},
{4, nullptr, "StorageCopyAlbumFile"},
@@ -62,6 +62,15 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
IAlbumAccessorService::~IAlbumAccessorService() = default;
+Result IAlbumAccessorService::GetAlbumFileList(
+ Out<u64> out_count, AlbumStorage storage,
+ OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries) {
+ LOG_INFO(Service_Capture, "called, storage={}", storage);
+
+ const Result result = manager->GetAlbumFileList(out_entries, *out_count, storage, 0);
+ R_RETURN(TranslateResult(result));
+}
+
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
file_id.application_id, file_id.storage, file_id.type);
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h
index 2cb9b4547..c7a5208e3 100644
--- a/src/core/hle/service/caps/caps_a.h
+++ b/src/core/hle/service/caps/caps_a.h
@@ -21,6 +21,9 @@ public:
~IAlbumAccessorService() override;
private:
+ Result GetAlbumFileList(Out<u64> out_count, AlbumStorage storage,
+ OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries);
+
Result DeleteAlbumFile(AlbumFileId file_id);
Result IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage);
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp
index 3ea862fad..39ae3a723 100644
--- a/src/core/hle/service/erpt/erpt.cpp
+++ b/src/core/hle/service/erpt/erpt.cpp
@@ -3,6 +3,8 @@
#include <memory>
+#include "common/logging/log.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/erpt/erpt.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
@@ -15,7 +17,7 @@ public:
explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "SubmitContext"},
+ {0, C<&ErrorReportContext::SubmitContext>, "SubmitContext"},
{1, nullptr, "CreateReportV0"},
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
@@ -36,6 +38,14 @@ public:
RegisterHandlers(functions);
}
+
+private:
+ Result SubmitContext(InBuffer<BufferAttr_HipcMapAlias> buffer_a,
+ InBuffer<BufferAttr_HipcMapAlias> buffer_b) {
+ LOG_WARNING(Service_SET, "(STUBBED) called, buffer_a_size={}, buffer_b_size={}",
+ buffer_a.size(), buffer_b.size());
+ R_SUCCEED();
+ }
};
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {
diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
index 63c2d3a58..2d49f30c8 100644
--- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
@@ -336,7 +336,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{1012, nullptr, "GetFsStackUsage"},
{1013, nullptr, "UnsetSaveDataRootPath"},
{1014, nullptr, "OutputMultiProgramTagAccessLog"},
- {1016, nullptr, "FlushAccessLogOnSdCard"},
+ {1016, &FSP_SRV::FlushAccessLogOnSdCard, "FlushAccessLogOnSdCard"},
{1017, nullptr, "OutputApplicationInfoAccessLog"},
{1018, nullptr, "SetDebugOption"},
{1019, nullptr, "UnsetDebugOption"},
@@ -706,6 +706,13 @@ void FSP_SRV::GetProgramIndexForAccessLog(HLERequestContext& ctx) {
rb.Push(access_log_program_index);
}
+void FSP_SRV::FlushAccessLogOnSdCard(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_FS, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void FSP_SRV::GetCacheStorageSize(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index{rp.Pop<s32>()};
diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h
index 26980af99..59406e6f9 100644
--- a/src/core/hle/service/filesystem/fsp/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h
@@ -58,6 +58,7 @@ private:
void SetGlobalAccessLogMode(HLERequestContext& ctx);
void GetGlobalAccessLogMode(HLERequestContext& ctx);
void OutputAccessLogToSdCard(HLERequestContext& ctx);
+ void FlushAccessLogOnSdCard(HLERequestContext& ctx);
void GetProgramIndexForAccessLog(HLERequestContext& ctx);
void OpenMultiCommitManager(HLERequestContext& ctx);
void GetCacheStorageSize(HLERequestContext& ctx);
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index cad755fa7..059ac3fc9 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -186,6 +186,10 @@ TimeManager::TimeManager(Core::System& system)
}
}
+TimeManager::~TimeManager() {
+ ResetTimeZoneBinary();
+}
+
Result TimeManager::SetupStandardSteadyClockCore() {
Common::UUID external_clock_source_id{};
auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h
index 1de93f8f9..bb4b65049 100644
--- a/src/core/hle/service/glue/time/manager.h
+++ b/src/core/hle/service/glue/time/manager.h
@@ -26,6 +26,7 @@ namespace Service::Glue::Time {
class TimeManager {
public:
explicit TimeManager(Core::System& system);
+ ~TimeManager();
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp
index ec9b0efb1..b801faef2 100644
--- a/src/core/hle/service/glue/time/static.cpp
+++ b/src/core/hle/service/glue/time/static.cpp
@@ -142,16 +142,18 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
}
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value);
+ };
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));
}
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
Out<bool> out_automatic_correction) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction);
- });
+ };
R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(
out_automatic_correction));
@@ -166,21 +168,27 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
}
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year);
+ };
R_RETURN(m_set_sys->GetSettingsItemValueImpl<s32>(*out_year, "time",
"standard_user_clock_initial_year"));
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient);
+ };
R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));
}
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point);
+ };
R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
out_time_point));
@@ -188,15 +196,18 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
Out<s64> out_time, const Service::PSC::Time::SystemClockContext& context) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time);
+ };
R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));
}
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot,
Service::PSC::Time::TimeType type) {
- SCOPE_EXIT(
- { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot);
+ };
R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));
}
@@ -205,11 +216,11 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
const Service::PSC::Time::SystemClockContext& user_context,
const Service::PSC::Time::SystemClockContext& network_context) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. type={} out_snapshot={} user_context={} network_context={}", type,
*out_snapshot, user_context, network_context);
- });
+ };
R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(
type, out_snapshot, user_context, network_context));
@@ -218,14 +229,18 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time,
InClockSnapshot a,
InClockSnapshot b) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time);
+ };
R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));
}
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
InClockSnapshot b) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time);
+ };
R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));
}
diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp
index 36f163419..f4d0c87d5 100644
--- a/src/core/hle/service/glue/time/time_zone.cpp
+++ b/src/core/hle/service/glue/time/time_zone.cpp
@@ -57,7 +57,9 @@ TimeZoneService::~TimeZoneService() = default;
Result TimeZoneService::GetDeviceLocationName(
Out<Service::PSC::Time::LocationName> out_location_name) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name);
+ };
R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));
}
@@ -94,7 +96,9 @@ Result TimeZoneService::SetDeviceLocationName(
}
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count);
+ };
R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));
}
@@ -102,10 +106,10 @@ Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
Result TimeZoneService::LoadLocationNameList(
Out<u32> out_count,
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
index, *out_count, out_names[0], out_names[1]);
- });
+ };
std::scoped_lock l{m_mutex};
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
@@ -124,7 +128,9 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule,
Result TimeZoneService::GetTimeZoneRuleVersion(
Out<Service::PSC::Time::RuleVersion> out_rule_version) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version);
+ };
R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));
}
@@ -132,10 +138,10 @@ Result TimeZoneService::GetTimeZoneRuleVersion(
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
Out<Service::PSC::Time::LocationName> location_name,
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name,
*out_time_point);
- });
+ };
R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point));
}
@@ -178,10 +184,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
Result TimeZoneService::ToCalendarTime(
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
- });
+ };
R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
}
@@ -189,10 +195,10 @@ Result TimeZoneService::ToCalendarTime(
Result TimeZoneService::ToCalendarTimeWithMyRule(
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
- });
+ };
R_RETURN(
m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
@@ -202,11 +208,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
const Service::PSC::Time::CalendarTime& calendar_time,
InRule rule) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
calendar_time, *out_count, out_times[0], out_times[1]);
- });
+ };
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
}
@@ -214,11 +220,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
Result TimeZoneService::ToPosixTimeWithMyRule(
Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
const Service::PSC::Time::CalendarTime& calendar_time) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
calendar_time, *out_count, out_times[0], out_times[1]);
- });
+ };
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
}
diff --git a/src/core/hle/service/ns/account_proxy_interface.cpp b/src/core/hle/service/ns/account_proxy_interface.cpp
new file mode 100644
index 000000000..e5041af66
--- /dev/null
+++ b/src/core/hle/service/ns/account_proxy_interface.cpp
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/account_proxy_interface.h"
+
+namespace Service::NS {
+
+IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
+ : ServiceFramework{system_, "IAccountProxyInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateUserAccount"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAccountProxyInterface::~IAccountProxyInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/account_proxy_interface.h b/src/core/hle/service/ns/account_proxy_interface.h
new file mode 100644
index 000000000..e944d2a75
--- /dev/null
+++ b/src/core/hle/service/ns/account_proxy_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
+public:
+ explicit IAccountProxyInterface(Core::System& system_);
+ ~IAccountProxyInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp
new file mode 100644
index 000000000..2e3a44c0d
--- /dev/null
+++ b/src/core/hle/service/ns/application_manager_interface.cpp
@@ -0,0 +1,519 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/file_sys/nca_metadata.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+
+namespace Service::NS {
+
+IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
+ : ServiceFramework{system_, "IApplicationManagerInterface"},
+ service_context{system, "IApplicationManagerInterface"},
+ record_update_system_event{service_context}, sd_card_mount_status_event{service_context},
+ gamecard_update_detection_event{service_context},
+ gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"},
+ {1, nullptr, "GenerateApplicationRecordCount"},
+ {2, D<&IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent>, "GetApplicationRecordUpdateSystemEvent"},
+ {3, nullptr, "GetApplicationViewDeprecated"},
+ {4, nullptr, "DeleteApplicationEntity"},
+ {5, nullptr, "DeleteApplicationCompletely"},
+ {6, nullptr, "IsAnyApplicationEntityRedundant"},
+ {7, nullptr, "DeleteRedundantApplicationEntity"},
+ {8, nullptr, "IsApplicationEntityMovable"},
+ {9, nullptr, "MoveApplicationEntity"},
+ {11, nullptr, "CalculateApplicationOccupiedSize"},
+ {16, nullptr, "PushApplicationRecord"},
+ {17, nullptr, "ListApplicationRecordContentMeta"},
+ {19, nullptr, "LaunchApplicationOld"},
+ {21, nullptr, "GetApplicationContentPath"},
+ {22, nullptr, "TerminateApplication"},
+ {23, nullptr, "ResolveApplicationContentPath"},
+ {26, nullptr, "BeginInstallApplication"},
+ {27, nullptr, "DeleteApplicationRecord"},
+ {30, nullptr, "RequestApplicationUpdateInfo"},
+ {31, nullptr, "Unknown31"},
+ {32, nullptr, "CancelApplicationDownload"},
+ {33, nullptr, "ResumeApplicationDownload"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"},
+ {39, nullptr, "CheckApplicationLaunchRights"},
+ {40, nullptr, "GetApplicationLogoData"},
+ {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
+ {42, nullptr, "CleanupSdCard"},
+ {43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
+ {44, D<&IApplicationManagerInterface::GetSdCardMountStatusChangedEvent>, "GetSdCardMountStatusChangedEvent"},
+ {45, nullptr, "GetGameCardAttachmentEvent"},
+ {46, nullptr, "GetGameCardAttachmentInfo"},
+ {47, nullptr, "GetTotalSpaceSize"},
+ {48, D<&IApplicationManagerInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
+ {49, nullptr, "GetSdCardRemovedEvent"},
+ {52, D<&IApplicationManagerInterface::GetGameCardUpdateDetectionEvent>, "GetGameCardUpdateDetectionEvent"},
+ {53, nullptr, "DisableApplicationAutoDelete"},
+ {54, nullptr, "EnableApplicationAutoDelete"},
+ {55, D<&IApplicationManagerInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
+ {56, nullptr, "SetApplicationTerminateResult"},
+ {57, nullptr, "ClearApplicationTerminateResult"},
+ {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
+ {59, D<&IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
+ {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+ {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
+ {62, nullptr, "GetGameCardStopper"},
+ {63, nullptr, "IsSystemProgramInstalled"},
+ {64, nullptr, "StartApplyDeltaTask"},
+ {65, nullptr, "GetRequestServerStopper"},
+ {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
+ {67, nullptr, "CancelApplicationApplyDelta"},
+ {68, nullptr, "ResumeApplicationApplyDelta"},
+ {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
+ {70, D<&IApplicationManagerInterface::ResumeAll>, "ResumeAll"},
+ {71, D<&IApplicationManagerInterface::GetStorageSize>, "GetStorageSize"},
+ {80, nullptr, "RequestDownloadApplication"},
+ {81, nullptr, "RequestDownloadAddOnContent"},
+ {82, nullptr, "DownloadApplication"},
+ {83, nullptr, "CheckApplicationResumeRights"},
+ {84, nullptr, "GetDynamicCommitEvent"},
+ {85, nullptr, "RequestUpdateApplication2"},
+ {86, nullptr, "EnableApplicationCrashReport"},
+ {87, nullptr, "IsApplicationCrashReportEnabled"},
+ {90, nullptr, "BoostSystemMemoryResourceLimit"},
+ {91, nullptr, "DeprecatedLaunchApplication"},
+ {92, nullptr, "GetRunningApplicationProgramId"},
+ {93, nullptr, "GetMainApplicationProgramIndex"},
+ {94, nullptr, "LaunchApplication"},
+ {95, nullptr, "GetApplicationLaunchInfo"},
+ {96, nullptr, "AcquireApplicationLaunchInfo"},
+ {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
+ {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
+ {99, nullptr, "LaunchDevMenu"},
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
+ {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
+ {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
+ {105, nullptr, "RequestResetToFactorySettingsSecurely"},
+ {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
+ {200, nullptr, "CalculateUserSaveDataStatistics"},
+ {201, nullptr, "DeleteUserSaveDataAll"},
+ {210, nullptr, "DeleteUserSystemSaveData"},
+ {211, nullptr, "DeleteSaveData"},
+ {220, nullptr, "UnregisterNetworkServiceAccount"},
+ {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
+ {300, nullptr, "GetApplicationShellEvent"},
+ {301, nullptr, "PopApplicationShellEventInfo"},
+ {302, nullptr, "LaunchLibraryApplet"},
+ {303, nullptr, "TerminateLibraryApplet"},
+ {304, nullptr, "LaunchSystemApplet"},
+ {305, nullptr, "TerminateSystemApplet"},
+ {306, nullptr, "LaunchOverlayApplet"},
+ {307, nullptr, "TerminateOverlayApplet"},
+ {400, D<&IApplicationManagerInterface::GetApplicationControlData>, "GetApplicationControlData"},
+ {401, nullptr, "InvalidateAllApplicationControlCache"},
+ {402, nullptr, "RequestDownloadApplicationControlData"},
+ {403, nullptr, "GetMaxApplicationControlCacheCount"},
+ {404, nullptr, "InvalidateApplicationControlCache"},
+ {405, nullptr, "ListApplicationControlCacheEntryInfo"},
+ {406, nullptr, "GetApplicationControlProperty"},
+ {407, nullptr, "ListApplicationTitle"},
+ {408, nullptr, "ListApplicationIcon"},
+ {502, nullptr, "RequestCheckGameCardRegistration"},
+ {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
+ {504, nullptr, "RequestRegisterGameCard"},
+ {505, D<&IApplicationManagerInterface::GetGameCardMountFailureEvent>, "GetGameCardMountFailureEvent"},
+ {506, nullptr, "IsGameCardInserted"},
+ {507, nullptr, "EnsureGameCardAccess"},
+ {508, nullptr, "GetLastGameCardMountFailureResult"},
+ {509, nullptr, "ListApplicationIdOnGameCard"},
+ {510, nullptr, "GetGameCardPlatformRegion"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {602, nullptr, "ListAvailableAddOnContent"},
+ {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
+ {604, nullptr, "RegisterContentsExternalKey"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {606, nullptr, "GetContentMetaStorage"},
+ {607, nullptr, "ListAvailableAddOnContent"},
+ {609, nullptr, "ListAvailabilityAssuredAddOnContent"},
+ {610, nullptr, "GetInstalledContentMetaStorage"},
+ {611, nullptr, "PrepareAddOnContent"},
+ {700, nullptr, "PushDownloadTaskList"},
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {900, nullptr, "GetApplicationRecord"},
+ {901, nullptr, "GetApplicationRecordProperty"},
+ {902, nullptr, "EnableApplicationAutoUpdate"},
+ {903, nullptr, "DisableApplicationAutoUpdate"},
+ {904, nullptr, "TouchApplication"},
+ {905, nullptr, "RequestApplicationUpdate"},
+ {906, D<&IApplicationManagerInterface::IsApplicationUpdateRequested>, "IsApplicationUpdateRequested"},
+ {907, nullptr, "WithdrawApplicationUpdateRequest"},
+ {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
+ {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
+ {910, nullptr, "HasApplicationRecord"},
+ {911, nullptr, "SetPreInstalledApplication"},
+ {912, nullptr, "ClearPreInstalledApplicationFlag"},
+ {913, nullptr, "ListAllApplicationRecord"},
+ {914, nullptr, "HideApplicationRecord"},
+ {915, nullptr, "ShowApplicationRecord"},
+ {916, nullptr, "IsApplicationAutoDeleteDisabled"},
+ {1000, nullptr, "RequestVerifyApplicationDeprecated"},
+ {1001, nullptr, "CorruptApplicationForDebug"},
+ {1002, nullptr, "RequestVerifyAddOnContentsRights"},
+ {1003, nullptr, "RequestVerifyApplication"},
+ {1004, nullptr, "CorruptContentForDebug"},
+ {1200, nullptr, "NeedsUpdateVulnerability"},
+ {1300, D<&IApplicationManagerInterface::IsAnyApplicationEntityInstalled>, "IsAnyApplicationEntityInstalled"},
+ {1301, nullptr, "DeleteApplicationContentEntities"},
+ {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
+ {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
+ {1304, nullptr, "DeleteApplicationContentEntity"},
+ {1305, nullptr, "TryDeleteRunningApplicationEntity"},
+ {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
+ {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
+ {1308, nullptr, "DeleteApplicationCompletelyForDebug"},
+ {1309, nullptr, "CleanupUnavailableAddOnContents"},
+ {1310, nullptr, "RequestMoveApplicationEntity"},
+ {1311, nullptr, "EstimateSizeToMove"},
+ {1312, nullptr, "HasMovableEntity"},
+ {1313, nullptr, "CleanupOrphanContents"},
+ {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
+ {1400, nullptr, "PrepareShutdown"},
+ {1500, nullptr, "FormatSdCard"},
+ {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
+ {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
+ {1504, nullptr, "InsertSdCard"},
+ {1505, nullptr, "RemoveSdCard"},
+ {1506, nullptr, "GetSdCardStartupStatus"},
+ {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
+ {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
+ {1700, nullptr, "ListApplicationDownloadingContentMeta"},
+ {1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"},
+ {1702, nullptr, "GetApplicationDownloadTaskStatus"},
+ {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
+ {1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"},
+ {1705, nullptr, "IsPatchAutoDeletableApplication"},
+ {1800, nullptr, "IsNotificationSetupCompleted"},
+ {1801, nullptr, "GetLastNotificationInfoCount"},
+ {1802, nullptr, "ListLastNotificationInfo"},
+ {1803, nullptr, "ListNotificationTask"},
+ {1900, nullptr, "IsActiveAccount"},
+ {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
+ {1902, nullptr, "GetApplicationTicketInfo"},
+ {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
+ {2000, nullptr, "GetSystemDeliveryInfo"},
+ {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
+ {2002, nullptr, "VerifyDeliveryProtocolVersion"},
+ {2003, nullptr, "GetApplicationDeliveryInfo"},
+ {2004, nullptr, "HasAllContentsToDeliver"},
+ {2005, nullptr, "CompareApplicationDeliveryInfo"},
+ {2006, nullptr, "CanDeliverApplication"},
+ {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
+ {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
+ {2009, nullptr, "EstimateRequiredSize"},
+ {2010, nullptr, "RequestReceiveApplication"},
+ {2011, nullptr, "CommitReceiveApplication"},
+ {2012, nullptr, "GetReceiveApplicationProgress"},
+ {2013, nullptr, "RequestSendApplication"},
+ {2014, nullptr, "GetSendApplicationProgress"},
+ {2015, nullptr, "CompareSystemDeliveryInfo"},
+ {2016, nullptr, "ListNotCommittedContentMeta"},
+ {2017, nullptr, "CreateDownloadTask"},
+ {2018, nullptr, "GetApplicationDeliveryInfoHash"},
+ {2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"},
+ {2051, nullptr, "InvalidateRightsIdCache"},
+ {2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"},
+ {2101, nullptr, "GetRawApplicationTerminateResult"},
+ {2150, nullptr, "CreateRightsEnvironment"},
+ {2151, nullptr, "DestroyRightsEnvironment"},
+ {2152, nullptr, "ActivateRightsEnvironment"},
+ {2153, nullptr, "DeactivateRightsEnvironment"},
+ {2154, nullptr, "ForceActivateRightsContextForExit"},
+ {2155, nullptr, "UpdateRightsEnvironmentStatus"},
+ {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
+ {2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
+ {2161, nullptr, "SetUsersToRightsEnvironment"},
+ {2170, nullptr, "GetRightsEnvironmentStatus"},
+ {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
+ {2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
+ {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
+ {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
+ {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
+ {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
+ {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
+ {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
+ {2250, nullptr, "RequestReportActiveELicence"},
+ {2300, nullptr, "ListEventLog"},
+ {2350, nullptr, "PerformAutoUpdateByApplicationId"},
+ {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
+ {2352, nullptr, "RequestResolveNoDownloadRightsError"},
+ {2353, nullptr, "GetApplicationDownloadTaskInfo"},
+ {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
+ {2355, nullptr, "PreferStorageEfficientUpdate"},
+ {2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
+ {2357, nullptr, "EnableMultiCoreDownload"},
+ {2358, nullptr, "DisableMultiCoreDownload"},
+ {2359, nullptr, "IsMultiCoreDownloadEnabled"},
+ {2400, nullptr, "GetPromotionInfo"},
+ {2401, nullptr, "CountPromotionInfo"},
+ {2402, nullptr, "ListPromotionInfo"},
+ {2403, nullptr, "ImportPromotionJsonForDebug"},
+ {2404, nullptr, "ClearPromotionInfoForDebug"},
+ {2500, nullptr, "ConfirmAvailableTime"},
+ {2510, nullptr, "CreateApplicationResource"},
+ {2511, nullptr, "GetApplicationResource"},
+ {2513, nullptr, "LaunchMicroApplication"},
+ {2514, nullptr, "ClearTaskOfAsyncTaskManager"},
+ {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
+ {2516, nullptr, "EnsureApplicationCertificate"},
+ {2517, nullptr, "CreateApplicationInstance"},
+ {2518, nullptr, "UpdateQualificationForDebug"},
+ {2519, nullptr, "IsQualificationTransitionSupported"},
+ {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
+ {2521, nullptr, "GetRightsUserChangedEvent"},
+ {2522, nullptr, "IsRomRedirectionAvailable"},
+ {2800, nullptr, "GetApplicationIdOfPreomia"},
+ {3000, nullptr, "RegisterDeviceLockKey"},
+ {3001, nullptr, "UnregisterDeviceLockKey"},
+ {3002, nullptr, "VerifyDeviceLockKey"},
+ {3003, nullptr, "HideApplicationIcon"},
+ {3004, nullptr, "ShowApplicationIcon"},
+ {3005, nullptr, "HideApplicationTitle"},
+ {3006, nullptr, "ShowApplicationTitle"},
+ {3007, nullptr, "EnableGameCard"},
+ {3008, nullptr, "DisableGameCard"},
+ {3009, nullptr, "EnableLocalContentShare"},
+ {3010, nullptr, "DisableLocalContentShare"},
+ {3011, nullptr, "IsApplicationIconHidden"},
+ {3012, nullptr, "IsApplicationTitleHidden"},
+ {3013, nullptr, "IsGameCardEnabled"},
+ {3014, nullptr, "IsLocalContentShareEnabled"},
+ {3050, nullptr, "ListAssignELicenseTaskResult"},
+ {9999, nullptr, "GetApplicationCertificate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationManagerInterface::~IApplicationManagerInterface() = default;
+
+Result IApplicationManagerInterface::GetApplicationControlData(
+ OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source, u64 application_id) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData(
+ out_buffer, out_actual_size, application_control_source, application_id));
+}
+
+Result IApplicationManagerInterface::GetApplicationDesiredLanguage(
+ Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationDesiredLanguage(
+ out_desired_language, supported_languages));
+}
+
+Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
+ Out<u64> out_language_code, ApplicationLanguage application_language) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(
+ IReadOnlyApplicationControlDataInterface(system).ConvertApplicationLanguageToLanguageCode(
+ out_language_code, application_language));
+}
+
+Result IApplicationManagerInterface::ListApplicationRecord(
+ OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, Out<s32> out_count,
+ s32 offset) {
+ const auto limit = out_records.size();
+
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ const auto& cache = system.GetContentProviderUnion();
+ const auto installed_games = cache.ListEntriesFilterOrigin(
+ std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
+
+ size_t i = 0;
+ u8 ii = 24;
+
+ for (const auto& [slot, game] : installed_games) {
+ if (i >= limit) {
+ break;
+ }
+ if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) {
+ continue;
+ }
+ if (offset > 0) {
+ offset--;
+ continue;
+ }
+
+ ApplicationRecord record{};
+ record.application_id = game.title_id;
+ record.type = ApplicationRecordType::Installed;
+ record.unknown = 0; // 2 = needs update
+ record.unknown2 = ii++;
+
+ out_records[i++] = record;
+ }
+
+ *out_count = static_cast<s32>(i);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+
+ record_update_system_event.Signal();
+ *out_event = record_update_system_event.GetHandle();
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetGameCardMountFailureEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = gamecard_mount_failure_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
+ Out<bool> out_is_any_application_entity_installed) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_is_any_application_entity_installed = true;
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationView(
+ OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ const auto size = std::min(out_application_views.size(), application_ids.size());
+ LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
+
+ for (size_t i = 0; i < size; i++) {
+ ApplicationView view{};
+ view.application_id = application_ids[i];
+ view.unk = 0x70000;
+ view.flags = 0x401f17;
+
+ out_application_views[i] = view;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
+ OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ const auto size = std::min(out_application_views.size(), application_ids.size());
+ LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
+
+ for (size_t i = 0; i < size; i++) {
+ ApplicationViewWithPromotionInfo view{};
+ view.view.application_id = application_ids[i];
+ view.view.unk = 0x70000;
+ view.view.flags = 0x401f17;
+ view.promotion = {};
+
+ out_application_views[i] = view;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationRightsOnClient(
+ OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
+ Common::UUID account_id, u32 flags, u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}",
+ flags, application_id, account_id.FormattedString());
+
+ if (!out_rights.empty()) {
+ ApplicationRightsOnClient rights{};
+ rights.application_id = application_id;
+ rights.uid = account_id;
+ rights.flags = 0;
+ rights.flags2 = 0;
+
+ out_rights[0] = rights;
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::CheckSdCardMountStatus() {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IContentManagementInterface(system).CheckSdCardMountStatus());
+}
+
+Result IApplicationManagerInterface::GetSdCardMountStatusChangedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = sd_card_mount_status_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IContentManagementInterface(system).GetFreeSpaceSize(out_free_space_size, storage_id));
+}
+
+Result IApplicationManagerInterface::GetGameCardUpdateDetectionEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = gamecard_update_detection_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::ResumeAll() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetStorageSize(Out<s64> out_total_space_size,
+ Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "called, storage_id={}", storage_id);
+ *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
+ *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::IsApplicationUpdateRequested(Out<bool> out_update_required,
+ Out<u32> out_update_version,
+ u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ *out_update_required = false;
+ *out_update_version = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result,
+ u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ *out_result = ResultSuccess;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_manager_interface.h b/src/core/hle/service/ns/application_manager_interface.h
new file mode 100644
index 000000000..350ec37ce
--- /dev/null
+++ b/src/core/hle/service/ns/application_manager_interface.h
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
+public:
+ explicit IApplicationManagerInterface(Core::System& system_);
+ ~IApplicationManagerInterface() override;
+
+ Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source,
+ u64 application_id);
+ Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
+ u32 supported_languages);
+ Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
+ ApplicationLanguage application_language);
+ Result ListApplicationRecord(OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records,
+ Out<s32> out_count, s32 offset);
+ Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
+ Result GetApplicationView(
+ OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result GetApplicationViewWithPromotionInfo(
+ OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result GetApplicationRightsOnClient(
+ OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
+ Common::UUID account_id, u32 flags, u64 application_id);
+ Result CheckSdCardMountStatus();
+ Result GetSdCardMountStatusChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
+ Result GetGameCardUpdateDetectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result ResumeAll();
+ Result GetStorageSize(Out<s64> out_total_space_size, Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id);
+ Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version,
+ u64 application_id);
+ Result CheckApplicationLaunchVersion(u64 application_id);
+ Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Event record_update_system_event;
+ Event sd_card_mount_status_event;
+ Event gamecard_update_detection_event;
+ Event gamecard_mount_status_event;
+ Event gamecard_mount_failure_event;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_version_interface.cpp b/src/core/hle/service/ns/application_version_interface.cpp
new file mode 100644
index 000000000..b89e127db
--- /dev/null
+++ b/src/core/hle/service/ns/application_version_interface.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/application_version_interface.h"
+
+namespace Service::NS {
+
+IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
+ : ServiceFramework{system_, "IApplicationVersionInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetLaunchRequiredVersion"},
+ {1, nullptr, "UpgradeLaunchRequiredVersion"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
+ {901, nullptr, "ListDefaultAutoUpdatePolicy"},
+ {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
+ {1000, nullptr, "PerformAutoUpdate"},
+ {1001, nullptr, "ListAutoUpdateSchedule"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationVersionInterface::~IApplicationVersionInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_version_interface.h b/src/core/hle/service/ns/application_version_interface.h
new file mode 100644
index 000000000..b288cff1b
--- /dev/null
+++ b/src/core/hle/service/ns/application_version_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
+public:
+ explicit IApplicationVersionInterface(Core::System& system_);
+ ~IApplicationVersionInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/content_management_interface.cpp b/src/core/hle/service/ns/content_management_interface.cpp
new file mode 100644
index 000000000..69bb3f6e4
--- /dev/null
+++ b/src/core/hle/service/ns/content_management_interface.cpp
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/common_funcs.h"
+#include "core/core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/ns_types.h"
+
+namespace Service::NS {
+
+IContentManagementInterface::IContentManagementInterface(Core::System& system_)
+ : ServiceFramework{system_, "IContentManagementInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {11, D<&IContentManagementInterface::CalculateApplicationOccupiedSize>, "CalculateApplicationOccupiedSize"},
+ {43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
+ {47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"},
+ {48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {607, nullptr, "IsAnyApplicationRunning"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IContentManagementInterface::~IContentManagementInterface() = default;
+
+Result IContentManagementInterface::CalculateApplicationOccupiedSize(
+ Out<ApplicationOccupiedSize> out_size, u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, application_id={:016X}", application_id);
+
+ using namespace Common::Literals;
+
+ constexpr ApplicationOccupiedSizeEntity stub_entity{
+ .storage_id = FileSys::StorageId::SdCard,
+ .app_size = 8_GiB,
+ .patch_size = 2_GiB,
+ .aoc_size = 12_MiB,
+ };
+
+ for (auto& entity : out_size->entities) {
+ entity = stub_entity;
+ }
+
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::CheckSdCardMountStatus() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::GetTotalSpaceSize(Out<s64> out_total_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
+ *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
+ *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/content_management_interface.h b/src/core/hle/service/ns/content_management_interface.h
new file mode 100644
index 000000000..2894628e5
--- /dev/null
+++ b/src/core/hle/service/ns/content_management_interface.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
+public:
+ explicit IContentManagementInterface(Core::System& system_);
+ ~IContentManagementInterface() override;
+
+public:
+ Result CalculateApplicationOccupiedSize(Out<ApplicationOccupiedSize> out_size,
+ u64 application_id);
+ Result CheckSdCardMountStatus();
+ Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id);
+ Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/develop_interface.cpp b/src/core/hle/service/ns/develop_interface.cpp
new file mode 100644
index 000000000..880bdbebb
--- /dev/null
+++ b/src/core/hle/service/ns/develop_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/develop_interface.h"
+
+namespace Service::NS {
+
+IDevelopInterface::IDevelopInterface(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "LaunchProgram"},
+ {1, nullptr, "TerminateProcess"},
+ {2, nullptr, "TerminateProgram"},
+ {4, nullptr, "GetShellEvent"},
+ {5, nullptr, "GetShellEventInfo"},
+ {6, nullptr, "TerminateApplication"},
+ {7, nullptr, "PrepareLaunchProgramFromHost"},
+ {8, nullptr, "LaunchApplicationFromHost"},
+ {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
+ {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
+ {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
+ {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
+ {13, nullptr, "CreateApplicationResourceForDevelop"},
+ {14, nullptr, "IsPreomiaForDevelop"},
+ {15, nullptr, "GetApplicationProgramIdFromHost"},
+ {16, nullptr, "RefreshCachedDebugValues"},
+ {17, nullptr, "PrepareLaunchApplicationFromHost"},
+ {18, nullptr, "GetLaunchEvent"},
+ {19, nullptr, "GetLaunchResult"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDevelopInterface::~IDevelopInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/develop_interface.h b/src/core/hle/service/ns/develop_interface.h
new file mode 100644
index 000000000..a9f81ccd6
--- /dev/null
+++ b/src/core/hle/service/ns/develop_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDevelopInterface final : public ServiceFramework<IDevelopInterface> {
+public:
+ explicit IDevelopInterface(Core::System& system_);
+ ~IDevelopInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/document_interface.cpp b/src/core/hle/service/ns/document_interface.cpp
new file mode 100644
index 000000000..51a1e46c0
--- /dev/null
+++ b/src/core/hle/service/ns/document_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/document_interface.h"
+
+namespace Service::NS {
+
+IDocumentInterface::IDocumentInterface(Core::System& system_)
+ : ServiceFramework{system_, "IDocumentInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {21, nullptr, "GetApplicationContentPath"},
+ {23, D<&IDocumentInterface::ResolveApplicationContentPath>, "ResolveApplicationContentPath"},
+ {92, D<&IDocumentInterface::GetRunningApplicationProgramId>, "GetRunningApplicationProgramId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDocumentInterface::~IDocumentInterface() = default;
+
+Result IDocumentInterface::ResolveApplicationContentPath(ContentPath content_path) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
+ content_path.file_system_proxy_type, content_path.program_id);
+ R_SUCCEED();
+}
+
+Result IDocumentInterface::GetRunningApplicationProgramId(Out<u64> out_program_id,
+ u64 caller_program_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
+ *out_program_id = system.GetApplicationProcessProgramID();
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/document_interface.h b/src/core/hle/service/ns/document_interface.h
new file mode 100644
index 000000000..cd461652c
--- /dev/null
+++ b/src/core/hle/service/ns/document_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
+public:
+ explicit IDocumentInterface(Core::System& system_);
+ ~IDocumentInterface() override;
+
+private:
+ Result ResolveApplicationContentPath(ContentPath content_path);
+ Result GetRunningApplicationProgramId(Out<u64> out_program_id, u64 caller_program_id);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/download_task_interface.cpp b/src/core/hle/service/ns/download_task_interface.cpp
new file mode 100644
index 000000000..62dc7f187
--- /dev/null
+++ b/src/core/hle/service/ns/download_task_interface.cpp
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/download_task_interface.h"
+
+namespace Service::NS {
+
+IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
+ : ServiceFramework{system_, "IDownloadTaskInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
+ {707, D<&IDownloadTaskInterface::EnableAutoCommit>, "EnableAutoCommit"},
+ {708, D<&IDownloadTaskInterface::DisableAutoCommit>, "DisableAutoCommit"},
+ {709, nullptr, "TriggerDynamicCommitEvent"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDownloadTaskInterface::~IDownloadTaskInterface() = default;
+
+Result IDownloadTaskInterface::EnableAutoCommit() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+Result IDownloadTaskInterface::DisableAutoCommit() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/download_task_interface.h b/src/core/hle/service/ns/download_task_interface.h
new file mode 100644
index 000000000..b1cb69cb8
--- /dev/null
+++ b/src/core/hle/service/ns/download_task_interface.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
+public:
+ explicit IDownloadTaskInterface(Core::System& system_);
+ ~IDownloadTaskInterface() override;
+
+private:
+ Result EnableAutoCommit();
+ Result DisableAutoCommit();
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/dynamic_rights_interface.cpp b/src/core/hle/service/ns/dynamic_rights_interface.cpp
new file mode 100644
index 000000000..ce81e203f
--- /dev/null
+++ b/src/core/hle/service/ns/dynamic_rights_interface.cpp
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/dynamic_rights_interface.h"
+
+namespace Service::NS {
+
+IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_)
+ : ServiceFramework{system_, "DynamicRightsInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestApplicationRightsOnServer"},
+ {1, nullptr, "RequestAssignRights"},
+ {4, nullptr, "DeprecatedRequestAssignRightsToResume"},
+ {5, D<&IDynamicRightsInterface::VerifyActivatedRightsOwners>, "VerifyActivatedRightsOwners"},
+ {6, nullptr, "DeprecatedGetApplicationRightsStatus"},
+ {7, nullptr, "RequestPrefetchForDynamicRights"},
+ {8, nullptr, "GetDynamicRightsState"},
+ {9, nullptr, "RequestApplicationRightsOnServerToResume"},
+ {10, nullptr, "RequestAssignRightsToResume"},
+ {11, nullptr, "GetActivatedRightsUsers"},
+ {12, nullptr, "GetApplicationRightsStatus"},
+ {13, D<&IDynamicRightsInterface::GetRunningApplicationStatus>, "GetRunningApplicationStatus"},
+ {14, nullptr, "SelectApplicationLicense"},
+ {15, nullptr, "RequestContentsAuthorizationToken"},
+ {16, nullptr, "QualifyUser"},
+ {17, nullptr, "QualifyUserWithProcessId"},
+ {18, D<&IDynamicRightsInterface::NotifyApplicationRightsCheckStart>, "NotifyApplicationRightsCheckStart"},
+ {19, nullptr, "UpdateUserList"},
+ {20, nullptr, "IsRightsLostUser"},
+ {21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
+ {22, nullptr, "GetLimitedApplicationLicense"},
+ {23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
+ {24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"},
+ {25, nullptr, "RequestProceedDynamicRightsState"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDynamicRightsInterface::~IDynamicRightsInterface() = default;
+
+Result IDynamicRightsInterface::NotifyApplicationRightsCheckStart() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IDynamicRightsInterface::GetRunningApplicationStatus(Out<u32> out_status,
+ u64 rights_handle) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
+ *out_status = 0;
+ R_SUCCEED();
+}
+
+Result IDynamicRightsInterface::VerifyActivatedRightsOwners(u64 rights_handle) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/dynamic_rights_interface.h b/src/core/hle/service/ns/dynamic_rights_interface.h
new file mode 100644
index 000000000..877e009b0
--- /dev/null
+++ b/src/core/hle/service/ns/dynamic_rights_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDynamicRightsInterface final : public ServiceFramework<IDynamicRightsInterface> {
+public:
+ explicit IDynamicRightsInterface(Core::System& system_);
+ ~IDynamicRightsInterface() override;
+
+private:
+ Result NotifyApplicationRightsCheckStart();
+ Result GetRunningApplicationStatus(Out<u32> out_status, u64 rights_handle);
+ Result VerifyActivatedRightsOwners(u64 rights_handle);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ecommerce_interface.cpp b/src/core/hle/service/ns/ecommerce_interface.cpp
new file mode 100644
index 000000000..76fc425f0
--- /dev/null
+++ b/src/core/hle/service/ns/ecommerce_interface.cpp
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/ecommerce_interface.h"
+
+namespace Service::NS {
+
+IECommerceInterface::IECommerceInterface(Core::System& system_)
+ : ServiceFramework{system_, "IECommerceInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestLinkDevice"},
+ {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
+ {2, nullptr, "RequestCleanupPreInstalledApplication"},
+ {3, nullptr, "RequestSyncRights"},
+ {4, nullptr, "RequestUnlinkDevice"},
+ {5, nullptr, "RequestRevokeAllELicense"},
+ {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IECommerceInterface::~IECommerceInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ecommerce_interface.h b/src/core/hle/service/ns/ecommerce_interface.h
new file mode 100644
index 000000000..4352101f4
--- /dev/null
+++ b/src/core/hle/service/ns/ecommerce_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
+public:
+ explicit IECommerceInterface(Core::System& system_);
+ ~IECommerceInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/factory_reset_interface.cpp b/src/core/hle/service/ns/factory_reset_interface.cpp
new file mode 100644
index 000000000..fd5cf7e1f
--- /dev/null
+++ b/src/core/hle/service/ns/factory_reset_interface.cpp
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/factory_reset_interface.h"
+
+namespace Service::NS {
+
+IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
+ : ServiceFramework{system_, "IFactoryResetInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
+ {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
+ {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
+ {105, nullptr, "RequestResetToFactorySettingsSecurely"},
+ {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IFactoryResetInterface::~IFactoryResetInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/factory_reset_interface.h b/src/core/hle/service/ns/factory_reset_interface.h
new file mode 100644
index 000000000..50d125123
--- /dev/null
+++ b/src/core/hle/service/ns/factory_reset_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
+public:
+ explicit IFactoryResetInterface(Core::System& system_);
+ ~IFactoryResetInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 19c3ff01b..8402e83cb 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -1,893 +1,38 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/arm/debug.h"
-#include "core/core.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/file_sys/vfs/vfs.h"
-#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/glue/glue_manager.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/errors.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
-#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/develop_interface.h"
#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/ns/pdm_qry.h"
+#include "core/hle/service/ns/platform_service_manager.h"
+#include "core/hle/service/ns/query_service.h"
+#include "core/hle/service/ns/service_getter_interface.h"
+#include "core/hle/service/ns/system_update_interface.h"
+#include "core/hle/service/ns/vulnerability_manager_interface.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/set/settings_server.h"
namespace Service::NS {
-IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
- : ServiceFramework{system_, "IAccountProxyInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "CreateUserAccount"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IAccountProxyInterface::~IAccountProxyInterface() = default;
-
-IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
- : ServiceFramework{system_, "IApplicationManagerInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "ListApplicationRecord"},
- {1, nullptr, "GenerateApplicationRecordCount"},
- {2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
- {3, nullptr, "GetApplicationViewDeprecated"},
- {4, nullptr, "DeleteApplicationEntity"},
- {5, nullptr, "DeleteApplicationCompletely"},
- {6, nullptr, "IsAnyApplicationEntityRedundant"},
- {7, nullptr, "DeleteRedundantApplicationEntity"},
- {8, nullptr, "IsApplicationEntityMovable"},
- {9, nullptr, "MoveApplicationEntity"},
- {11, nullptr, "CalculateApplicationOccupiedSize"},
- {16, nullptr, "PushApplicationRecord"},
- {17, nullptr, "ListApplicationRecordContentMeta"},
- {19, nullptr, "LaunchApplicationOld"},
- {21, nullptr, "GetApplicationContentPath"},
- {22, nullptr, "TerminateApplication"},
- {23, nullptr, "ResolveApplicationContentPath"},
- {26, nullptr, "BeginInstallApplication"},
- {27, nullptr, "DeleteApplicationRecord"},
- {30, nullptr, "RequestApplicationUpdateInfo"},
- {31, nullptr, "Unknown31"},
- {32, nullptr, "CancelApplicationDownload"},
- {33, nullptr, "ResumeApplicationDownload"},
- {35, nullptr, "UpdateVersionList"},
- {36, nullptr, "PushLaunchVersion"},
- {37, nullptr, "ListRequiredVersion"},
- {38, nullptr, "CheckApplicationLaunchVersion"},
- {39, nullptr, "CheckApplicationLaunchRights"},
- {40, nullptr, "GetApplicationLogoData"},
- {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
- {42, nullptr, "CleanupSdCard"},
- {43, nullptr, "CheckSdCardMountStatus"},
- {44, nullptr, "GetSdCardMountStatusChangedEvent"},
- {45, nullptr, "GetGameCardAttachmentEvent"},
- {46, nullptr, "GetGameCardAttachmentInfo"},
- {47, nullptr, "GetTotalSpaceSize"},
- {48, nullptr, "GetFreeSpaceSize"},
- {49, nullptr, "GetSdCardRemovedEvent"},
- {52, nullptr, "GetGameCardUpdateDetectionEvent"},
- {53, nullptr, "DisableApplicationAutoDelete"},
- {54, nullptr, "EnableApplicationAutoDelete"},
- {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"},
- {56, nullptr, "SetApplicationTerminateResult"},
- {57, nullptr, "ClearApplicationTerminateResult"},
- {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
- {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"},
- {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
- {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
- {62, nullptr, "GetGameCardStopper"},
- {63, nullptr, "IsSystemProgramInstalled"},
- {64, nullptr, "StartApplyDeltaTask"},
- {65, nullptr, "GetRequestServerStopper"},
- {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
- {67, nullptr, "CancelApplicationApplyDelta"},
- {68, nullptr, "ResumeApplicationApplyDelta"},
- {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
- {70, nullptr, "ResumeAll"},
- {71, nullptr, "GetStorageSize"},
- {80, nullptr, "RequestDownloadApplication"},
- {81, nullptr, "RequestDownloadAddOnContent"},
- {82, nullptr, "DownloadApplication"},
- {83, nullptr, "CheckApplicationResumeRights"},
- {84, nullptr, "GetDynamicCommitEvent"},
- {85, nullptr, "RequestUpdateApplication2"},
- {86, nullptr, "EnableApplicationCrashReport"},
- {87, nullptr, "IsApplicationCrashReportEnabled"},
- {90, nullptr, "BoostSystemMemoryResourceLimit"},
- {91, nullptr, "DeprecatedLaunchApplication"},
- {92, nullptr, "GetRunningApplicationProgramId"},
- {93, nullptr, "GetMainApplicationProgramIndex"},
- {94, nullptr, "LaunchApplication"},
- {95, nullptr, "GetApplicationLaunchInfo"},
- {96, nullptr, "AcquireApplicationLaunchInfo"},
- {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
- {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
- {99, nullptr, "LaunchDevMenu"},
- {100, nullptr, "ResetToFactorySettings"},
- {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
- {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
- {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
- {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
- {105, nullptr, "RequestResetToFactorySettingsSecurely"},
- {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
- {200, nullptr, "CalculateUserSaveDataStatistics"},
- {201, nullptr, "DeleteUserSaveDataAll"},
- {210, nullptr, "DeleteUserSystemSaveData"},
- {211, nullptr, "DeleteSaveData"},
- {220, nullptr, "UnregisterNetworkServiceAccount"},
- {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
- {300, nullptr, "GetApplicationShellEvent"},
- {301, nullptr, "PopApplicationShellEventInfo"},
- {302, nullptr, "LaunchLibraryApplet"},
- {303, nullptr, "TerminateLibraryApplet"},
- {304, nullptr, "LaunchSystemApplet"},
- {305, nullptr, "TerminateSystemApplet"},
- {306, nullptr, "LaunchOverlayApplet"},
- {307, nullptr, "TerminateOverlayApplet"},
- {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"},
- {401, nullptr, "InvalidateAllApplicationControlCache"},
- {402, nullptr, "RequestDownloadApplicationControlData"},
- {403, nullptr, "GetMaxApplicationControlCacheCount"},
- {404, nullptr, "InvalidateApplicationControlCache"},
- {405, nullptr, "ListApplicationControlCacheEntryInfo"},
- {406, nullptr, "GetApplicationControlProperty"},
- {407, nullptr, "ListApplicationTitle"},
- {408, nullptr, "ListApplicationIcon"},
- {502, nullptr, "RequestCheckGameCardRegistration"},
- {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
- {504, nullptr, "RequestRegisterGameCard"},
- {505, nullptr, "GetGameCardMountFailureEvent"},
- {506, nullptr, "IsGameCardInserted"},
- {507, nullptr, "EnsureGameCardAccess"},
- {508, nullptr, "GetLastGameCardMountFailureResult"},
- {509, nullptr, "ListApplicationIdOnGameCard"},
- {510, nullptr, "GetGameCardPlatformRegion"},
- {600, nullptr, "CountApplicationContentMeta"},
- {601, nullptr, "ListApplicationContentMetaStatus"},
- {602, nullptr, "ListAvailableAddOnContent"},
- {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
- {604, nullptr, "RegisterContentsExternalKey"},
- {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
- {606, nullptr, "GetContentMetaStorage"},
- {607, nullptr, "ListAvailableAddOnContent"},
- {609, nullptr, "ListAvailabilityAssuredAddOnContent"},
- {610, nullptr, "GetInstalledContentMetaStorage"},
- {611, nullptr, "PrepareAddOnContent"},
- {700, nullptr, "PushDownloadTaskList"},
- {701, nullptr, "ClearTaskStatusList"},
- {702, nullptr, "RequestDownloadTaskList"},
- {703, nullptr, "RequestEnsureDownloadTask"},
- {704, nullptr, "ListDownloadTaskStatus"},
- {705, nullptr, "RequestDownloadTaskListData"},
- {800, nullptr, "RequestVersionList"},
- {801, nullptr, "ListVersionList"},
- {802, nullptr, "RequestVersionListData"},
- {900, nullptr, "GetApplicationRecord"},
- {901, nullptr, "GetApplicationRecordProperty"},
- {902, nullptr, "EnableApplicationAutoUpdate"},
- {903, nullptr, "DisableApplicationAutoUpdate"},
- {904, nullptr, "TouchApplication"},
- {905, nullptr, "RequestApplicationUpdate"},
- {906, nullptr, "IsApplicationUpdateRequested"},
- {907, nullptr, "WithdrawApplicationUpdateRequest"},
- {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
- {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
- {910, nullptr, "HasApplicationRecord"},
- {911, nullptr, "SetPreInstalledApplication"},
- {912, nullptr, "ClearPreInstalledApplicationFlag"},
- {913, nullptr, "ListAllApplicationRecord"},
- {914, nullptr, "HideApplicationRecord"},
- {915, nullptr, "ShowApplicationRecord"},
- {916, nullptr, "IsApplicationAutoDeleteDisabled"},
- {1000, nullptr, "RequestVerifyApplicationDeprecated"},
- {1001, nullptr, "CorruptApplicationForDebug"},
- {1002, nullptr, "RequestVerifyAddOnContentsRights"},
- {1003, nullptr, "RequestVerifyApplication"},
- {1004, nullptr, "CorruptContentForDebug"},
- {1200, nullptr, "NeedsUpdateVulnerability"},
- {1300, nullptr, "IsAnyApplicationEntityInstalled"},
- {1301, nullptr, "DeleteApplicationContentEntities"},
- {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
- {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
- {1304, nullptr, "DeleteApplicationContentEntity"},
- {1305, nullptr, "TryDeleteRunningApplicationEntity"},
- {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
- {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
- {1308, nullptr, "DeleteApplicationCompletelyForDebug"},
- {1309, nullptr, "CleanupUnavailableAddOnContents"},
- {1310, nullptr, "RequestMoveApplicationEntity"},
- {1311, nullptr, "EstimateSizeToMove"},
- {1312, nullptr, "HasMovableEntity"},
- {1313, nullptr, "CleanupOrphanContents"},
- {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
- {1400, nullptr, "PrepareShutdown"},
- {1500, nullptr, "FormatSdCard"},
- {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
- {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
- {1504, nullptr, "InsertSdCard"},
- {1505, nullptr, "RemoveSdCard"},
- {1506, nullptr, "GetSdCardStartupStatus"},
- {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
- {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
- {1700, nullptr, "ListApplicationDownloadingContentMeta"},
- {1701, nullptr, "GetApplicationView"},
- {1702, nullptr, "GetApplicationDownloadTaskStatus"},
- {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
- {1704, nullptr, "GetApplicationViewWithPromotionInfo"},
- {1705, nullptr, "IsPatchAutoDeletableApplication"},
- {1800, nullptr, "IsNotificationSetupCompleted"},
- {1801, nullptr, "GetLastNotificationInfoCount"},
- {1802, nullptr, "ListLastNotificationInfo"},
- {1803, nullptr, "ListNotificationTask"},
- {1900, nullptr, "IsActiveAccount"},
- {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
- {1902, nullptr, "GetApplicationTicketInfo"},
- {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
- {2000, nullptr, "GetSystemDeliveryInfo"},
- {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
- {2002, nullptr, "VerifyDeliveryProtocolVersion"},
- {2003, nullptr, "GetApplicationDeliveryInfo"},
- {2004, nullptr, "HasAllContentsToDeliver"},
- {2005, nullptr, "CompareApplicationDeliveryInfo"},
- {2006, nullptr, "CanDeliverApplication"},
- {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
- {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
- {2009, nullptr, "EstimateRequiredSize"},
- {2010, nullptr, "RequestReceiveApplication"},
- {2011, nullptr, "CommitReceiveApplication"},
- {2012, nullptr, "GetReceiveApplicationProgress"},
- {2013, nullptr, "RequestSendApplication"},
- {2014, nullptr, "GetSendApplicationProgress"},
- {2015, nullptr, "CompareSystemDeliveryInfo"},
- {2016, nullptr, "ListNotCommittedContentMeta"},
- {2017, nullptr, "CreateDownloadTask"},
- {2018, nullptr, "GetApplicationDeliveryInfoHash"},
- {2050, nullptr, "GetApplicationRightsOnClient"},
- {2051, nullptr, "InvalidateRightsIdCache"},
- {2100, nullptr, "GetApplicationTerminateResult"},
- {2101, nullptr, "GetRawApplicationTerminateResult"},
- {2150, nullptr, "CreateRightsEnvironment"},
- {2151, nullptr, "DestroyRightsEnvironment"},
- {2152, nullptr, "ActivateRightsEnvironment"},
- {2153, nullptr, "DeactivateRightsEnvironment"},
- {2154, nullptr, "ForceActivateRightsContextForExit"},
- {2155, nullptr, "UpdateRightsEnvironmentStatus"},
- {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
- {2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
- {2161, nullptr, "SetUsersToRightsEnvironment"},
- {2170, nullptr, "GetRightsEnvironmentStatus"},
- {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
- {2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
- {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
- {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
- {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
- {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
- {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
- {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
- {2250, nullptr, "RequestReportActiveELicence"},
- {2300, nullptr, "ListEventLog"},
- {2350, nullptr, "PerformAutoUpdateByApplicationId"},
- {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
- {2352, nullptr, "RequestResolveNoDownloadRightsError"},
- {2353, nullptr, "GetApplicationDownloadTaskInfo"},
- {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
- {2355, nullptr, "PreferStorageEfficientUpdate"},
- {2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
- {2357, nullptr, "EnableMultiCoreDownload"},
- {2358, nullptr, "DisableMultiCoreDownload"},
- {2359, nullptr, "IsMultiCoreDownloadEnabled"},
- {2400, nullptr, "GetPromotionInfo"},
- {2401, nullptr, "CountPromotionInfo"},
- {2402, nullptr, "ListPromotionInfo"},
- {2403, nullptr, "ImportPromotionJsonForDebug"},
- {2404, nullptr, "ClearPromotionInfoForDebug"},
- {2500, nullptr, "ConfirmAvailableTime"},
- {2510, nullptr, "CreateApplicationResource"},
- {2511, nullptr, "GetApplicationResource"},
- {2513, nullptr, "LaunchMicroApplication"},
- {2514, nullptr, "ClearTaskOfAsyncTaskManager"},
- {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
- {2516, nullptr, "EnsureApplicationCertificate"},
- {2517, nullptr, "CreateApplicationInstance"},
- {2518, nullptr, "UpdateQualificationForDebug"},
- {2519, nullptr, "IsQualificationTransitionSupported"},
- {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
- {2521, nullptr, "GetRightsUserChangedEvent"},
- {2522, nullptr, "IsRomRedirectionAvailable"},
- {2800, nullptr, "GetApplicationIdOfPreomia"},
- {3000, nullptr, "RegisterDeviceLockKey"},
- {3001, nullptr, "UnregisterDeviceLockKey"},
- {3002, nullptr, "VerifyDeviceLockKey"},
- {3003, nullptr, "HideApplicationIcon"},
- {3004, nullptr, "ShowApplicationIcon"},
- {3005, nullptr, "HideApplicationTitle"},
- {3006, nullptr, "ShowApplicationTitle"},
- {3007, nullptr, "EnableGameCard"},
- {3008, nullptr, "DisableGameCard"},
- {3009, nullptr, "EnableLocalContentShare"},
- {3010, nullptr, "DisableLocalContentShare"},
- {3011, nullptr, "IsApplicationIconHidden"},
- {3012, nullptr, "IsApplicationTitleHidden"},
- {3013, nullptr, "IsGameCardEnabled"},
- {3014, nullptr, "IsLocalContentShareEnabled"},
- {3050, nullptr, "ListAssignELicenseTaskResult"},
- {9999, nullptr, "GetApplicationCertificate"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationManagerInterface::~IApplicationManagerInterface() = default;
-
-void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto flag = rp.PopRaw<u64>();
- LOG_DEBUG(Service_NS, "called with flag={:016X}", flag);
-
- const auto title_id = rp.PopRaw<u64>();
-
- const auto size = ctx.GetWriteBufferSize();
-
- const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
- system.GetContentProvider()};
- 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(ResultUnknown);
- 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(ResultUnknown);
- 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(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(out.size()));
-}
-
-void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto supported_languages = rp.Pop<u32>();
-
- u8 desired_language{};
- const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages);
- if (res == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(desired_language);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
- const u32 supported_languages) {
- LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
-
- // Get language code from settings
- const auto language_code =
- Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
-
- // Convert to application language, get priority list
- const auto application_language = ConvertToApplicationLanguage(language_code);
- if (application_language == std::nullopt) {
- LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
- language_code);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
- const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
- if (!priority_list) {
- LOG_ERROR(Service_NS,
- "Could not find application language priorities! application_language={}",
- *application_language);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
-
- // Try to find a valid language.
- for (const auto lang : *priority_list) {
- const auto supported_flag = GetSupportedLanguageFlag(lang);
- if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
- *out_desired_language = static_cast<u8>(lang);
- return ResultSuccess;
- }
- }
-
- LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
- supported_languages);
- return Service::NS::ResultApplicationLanguageNotFound;
-}
-
-void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
- HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto application_language = rp.Pop<u8>();
-
- u64 language_code{};
- const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language);
- if (res == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(language_code);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
- u64* out_language_code, u8 application_language) {
- const auto language_code =
- ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
- if (language_code == std::nullopt) {
- LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
-
- *out_language_code = static_cast<u64>(*language_code);
- return ResultSuccess;
-}
-
-IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
- : ServiceFramework{system_, "IApplicationVersionInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetLaunchRequiredVersion"},
- {1, nullptr, "UpgradeLaunchRequiredVersion"},
- {35, nullptr, "UpdateVersionList"},
- {36, nullptr, "PushLaunchVersion"},
- {37, nullptr, "ListRequiredVersion"},
- {800, nullptr, "RequestVersionList"},
- {801, nullptr, "ListVersionList"},
- {802, nullptr, "RequestVersionListData"},
- {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
- {901, nullptr, "ListDefaultAutoUpdatePolicy"},
- {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
- {1000, nullptr, "PerformAutoUpdate"},
- {1001, nullptr, "ListAutoUpdateSchedule"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationVersionInterface::~IApplicationVersionInterface() = default;
-
-IContentManagementInterface::IContentManagementInterface(Core::System& system_)
- : ServiceFramework{system_, "IContentManagementInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {11, nullptr, "CalculateApplicationOccupiedSize"},
- {43, nullptr, "CheckSdCardMountStatus"},
- {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
- {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
- {600, nullptr, "CountApplicationContentMeta"},
- {601, nullptr, "ListApplicationContentMetaStatus"},
- {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
- {607, nullptr, "IsAnyApplicationRunning"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IContentManagementInterface::~IContentManagementInterface() = default;
-
-void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto storage{rp.PopEnum<FileSys::StorageId>()};
-
- LOG_INFO(Service_Capture, "called, storage={}", storage);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
-}
-
-void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto storage{rp.PopEnum<FileSys::StorageId>()};
-
- LOG_INFO(Service_Capture, "called, storage={}", storage);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
-}
-
-IDocumentInterface::IDocumentInterface(Core::System& system_)
- : ServiceFramework{system_, "IDocumentInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {21, nullptr, "GetApplicationContentPath"},
- {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"},
- {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDocumentInterface::~IDocumentInterface() = default;
-
-void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) {
- struct ContentPath {
- u8 file_system_proxy_type;
- u64 program_id;
- };
- static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size");
-
- IPC::RequestParser rp{ctx};
- auto content_path = rp.PopRaw<ContentPath>();
- LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
- content_path.file_system_proxy_type, content_path.program_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto caller_program_id = rp.PopRaw<u64>();
- LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetApplicationProcessProgramID());
-}
-
-IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
- : ServiceFramework{system_, "IDownloadTaskInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {701, nullptr, "ClearTaskStatusList"},
- {702, nullptr, "RequestDownloadTaskList"},
- {703, nullptr, "RequestEnsureDownloadTask"},
- {704, nullptr, "ListDownloadTaskStatus"},
- {705, nullptr, "RequestDownloadTaskListData"},
- {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
- {707, nullptr, "EnableAutoCommit"},
- {708, nullptr, "DisableAutoCommit"},
- {709, nullptr, "TriggerDynamicCommitEvent"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDownloadTaskInterface::~IDownloadTaskInterface() = default;
-
-IECommerceInterface::IECommerceInterface(Core::System& system_)
- : ServiceFramework{system_, "IECommerceInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "RequestLinkDevice"},
- {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
- {2, nullptr, "RequestCleanupPreInstalledApplication"},
- {3, nullptr, "RequestSyncRights"},
- {4, nullptr, "RequestUnlinkDevice"},
- {5, nullptr, "RequestRevokeAllELicense"},
- {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IECommerceInterface::~IECommerceInterface() = default;
-
-IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
- : ServiceFramework{system_, "IFactoryResetInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {100, nullptr, "ResetToFactorySettings"},
- {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
- {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
- {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
- {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
- {105, nullptr, "RequestResetToFactorySettingsSecurely"},
- {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IFactoryResetInterface::~IFactoryResetInterface() = default;
-
-IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
- : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
- static const FunctionInfo functions[] = {
- {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"},
- {1, nullptr, "NotifyApplicationFailure"},
- {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
-
-void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 program_id = rp.PopRaw<u64>();
- LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(1);
-}
-
-void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto result = rp.PopRaw<Result>();
- LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(0);
-}
-
-IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
- Core::System& system_)
- : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"},
- {1, nullptr, "GetApplicationDesiredLanguage"},
- {2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
- {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
- {4, nullptr, "SelectApplicationDesiredLanguage"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
-
-void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) {
- enum class ApplicationControlSource : u8 {
- CacheOnly,
- Storage,
- StorageOnly,
- };
-
- struct RequestParameters {
- ApplicationControlSource source;
- u64 application_id;
- };
- static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
-
- IPC::RequestParser rp{ctx};
- std::vector<u8> nacp_data{};
- const auto parameters{rp.PopRaw<RequestParameters>()};
- const auto result =
- system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
-
- if (result == ResultSuccess) {
- ctx.WriteBuffer(nacp_data.data(), nacp_data.size());
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {7988, nullptr, "GetDynamicRightsInterface"},
- {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
- {7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
- {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
- {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
- {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
- {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
- {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"},
- {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
- {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
- {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-NS::~NS() = default;
-
-std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
- return GetInterface<IApplicationManagerInterface>(system);
-}
-
-class NS_DEV final : public ServiceFramework<NS_DEV> {
-public:
- explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "LaunchProgram"},
- {1, nullptr, "TerminateProcess"},
- {2, nullptr, "TerminateProgram"},
- {4, nullptr, "GetShellEvent"},
- {5, nullptr, "GetShellEventInfo"},
- {6, nullptr, "TerminateApplication"},
- {7, nullptr, "PrepareLaunchProgramFromHost"},
- {8, nullptr, "LaunchApplicationFromHost"},
- {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
- {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
- {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
- {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
- {13, nullptr, "CreateApplicationResourceForDevelop"},
- {14, nullptr, "IsPreomiaForDevelop"},
- {15, nullptr, "GetApplicationProgramIdFromHost"},
- {16, nullptr, "RefreshCachedDebugValues"},
- {17, nullptr, "PrepareLaunchApplicationFromHost"},
- {18, nullptr, "GetLaunchEvent"},
- {19, nullptr, "GetLaunchResult"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
-public:
- explicit ISystemUpdateControl(Core::System& system_)
- : ServiceFramework{system_, "ISystemUpdateControl"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "HasDownloaded"},
- {1, nullptr, "RequestCheckLatestUpdate"},
- {2, nullptr, "RequestDownloadLatestUpdate"},
- {3, nullptr, "GetDownloadProgress"},
- {4, nullptr, "ApplyDownloadedUpdate"},
- {5, nullptr, "RequestPrepareCardUpdate"},
- {6, nullptr, "GetPrepareCardUpdateProgress"},
- {7, nullptr, "HasPreparedCardUpdate"},
- {8, nullptr, "ApplyCardUpdate"},
- {9, nullptr, "GetDownloadedEulaDataSize"},
- {10, nullptr, "GetDownloadedEulaData"},
- {11, nullptr, "SetupCardUpdate"},
- {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
- {13, nullptr, "GetPreparedCardUpdateEulaData"},
- {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
- {15, nullptr, "HasReceived"},
- {16, nullptr, "RequestReceiveSystemUpdate"},
- {17, nullptr, "GetReceiveProgress"},
- {18, nullptr, "ApplyReceivedUpdate"},
- {19, nullptr, "GetReceivedEulaDataSize"},
- {20, nullptr, "GetReceivedEulaData"},
- {21, nullptr, "SetupToReceiveSystemUpdate"},
- {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class NS_SU final : public ServiceFramework<NS_SU> {
-public:
- explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetBackgroundNetworkUpdateState"},
- {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
- {2, nullptr, "NotifyExFatDriverRequired"},
- {3, nullptr, "ClearExFatDriverStatusForDebug"},
- {4, nullptr, "RequestBackgroundNetworkUpdate"},
- {5, nullptr, "NotifyBackgroundNetworkUpdate"},
- {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
- {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
- {10, nullptr, "NotifySystemUpdateForContentDelivery"},
- {11, nullptr, "PrepareShutdown"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {14, nullptr, "Unknown14"},
- {15, nullptr, "Unknown15"},
- {16, nullptr, "DestroySystemUpdateTask"},
- {17, nullptr, "RequestSendSystemUpdate"},
- {18, nullptr, "GetSendSystemUpdateProgress"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void OpenSystemUpdateControl(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemUpdateControl>(system);
- }
-};
-
-class NS_VM final : public ServiceFramework<NS_VM> {
-public:
- explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1200, &NS_VM::NeedsUpdateVulnerability, "NeedsUpdateVulnerability"},
- {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
- {1202, nullptr, "GetSafeSystemVersion"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void NeedsUpdateVulnerability(HLERequestContext& ctx) {
- LOG_WARNING(Service_NS, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(false);
- }
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system));
- server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system));
- server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system));
- server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system));
- server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system));
- server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system));
-
- server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system));
- server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system));
- server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system));
- server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system));
+ server_manager->RegisterNamedService(
+ "ns:am2", std::make_shared<IServiceGetterInterface>(system, "ns:am2"));
+ server_manager->RegisterNamedService(
+ "ns:ec", std::make_shared<IServiceGetterInterface>(system, "ns:ec"));
+ server_manager->RegisterNamedService(
+ "ns:rid", std::make_shared<IServiceGetterInterface>(system, "ns:rid"));
+ server_manager->RegisterNamedService(
+ "ns:rt", std::make_shared<IServiceGetterInterface>(system, "ns:rt"));
+ server_manager->RegisterNamedService(
+ "ns:web", std::make_shared<IServiceGetterInterface>(system, "ns:web"));
+ server_manager->RegisterNamedService(
+ "ns:ro", std::make_shared<IServiceGetterInterface>(system, "ns:ro"));
+
+ server_manager->RegisterNamedService("ns:dev", std::make_shared<IDevelopInterface>(system));
+ server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system));
+ server_manager->RegisterNamedService("ns:vm",
+ std::make_shared<IVulnerabilityManagerInterface>(system));
+ server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system));
server_manager->RegisterNamedService("pl:s",
std::make_shared<IPlatformServiceManager>(system, "pl:s"));
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 9ee306ef9..f79b4ae3d 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -3,141 +3,12 @@
#pragma once
-#include "core/hle/service/service.h"
-
namespace Core {
class System;
}
-namespace Service {
-
-namespace FileSystem {
-class FileSystemController;
-} // namespace FileSystem
-
-namespace NS {
-
-class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
-public:
- explicit IAccountProxyInterface(Core::System& system_);
- ~IAccountProxyInterface() override;
-};
-
-class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
-public:
- explicit IApplicationManagerInterface(Core::System& system_);
- ~IApplicationManagerInterface() override;
-
- Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages);
- Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code,
- u8 application_language);
-
-private:
- void GetApplicationControlData(HLERequestContext& ctx);
- void GetApplicationDesiredLanguage(HLERequestContext& ctx);
- void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
-};
-
-class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
-public:
- explicit IApplicationVersionInterface(Core::System& system_);
- ~IApplicationVersionInterface() override;
-};
-
-class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
-public:
- explicit IContentManagementInterface(Core::System& system_);
- ~IContentManagementInterface() override;
-
-private:
- void GetTotalSpaceSize(HLERequestContext& ctx);
- void GetFreeSpaceSize(HLERequestContext& ctx);
-};
-
-class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
-public:
- explicit IDocumentInterface(Core::System& system_);
- ~IDocumentInterface() override;
-
-private:
- void ResolveApplicationContentPath(HLERequestContext& ctx);
- void GetRunningApplicationProgramId(HLERequestContext& ctx);
-};
-
-class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
-public:
- explicit IDownloadTaskInterface(Core::System& system_);
- ~IDownloadTaskInterface() override;
-};
-
-class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
-public:
- explicit IECommerceInterface(Core::System& system_);
- ~IECommerceInterface() override;
-};
-
-class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
-public:
- explicit IFactoryResetInterface(Core::System& system_);
- ~IFactoryResetInterface() override;
-};
-
-class IReadOnlyApplicationRecordInterface final
- : public ServiceFramework<IReadOnlyApplicationRecordInterface> {
-public:
- explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
- ~IReadOnlyApplicationRecordInterface() override;
-
-private:
- void HasApplicationRecord(HLERequestContext& ctx);
- void IsDataCorruptedResult(HLERequestContext& ctx);
-};
-
-class IReadOnlyApplicationControlDataInterface final
- : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
-public:
- explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
- ~IReadOnlyApplicationControlDataInterface() override;
-
-private:
- void GetApplicationControlData(HLERequestContext& ctx);
-};
-
-class NS final : public ServiceFramework<NS> {
-public:
- explicit NS(const char* name, Core::System& system_);
- ~NS() override;
-
- std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const;
-
-private:
- template <typename T, typename... Args>
- void PushInterface(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<T>(system);
- }
-
- void PushIApplicationManagerInterface(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationManagerInterface>(system);
- }
-
- template <typename T, typename... Args>
- std::shared_ptr<T> GetInterface(Args&&... args) const {
- static_assert(std::is_base_of_v<SessionRequestHandler, T>,
- "Not a base of ServiceFrameworkBase");
-
- return std::make_shared<T>(std::forward<Args>(args)...);
- }
-};
+namespace Service::NS {
void LoopProcess(Core::System& system);
-} // namespace NS
-} // namespace Service
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/ns_results.h
index 16d2ea6f7..16d2ea6f7 100644
--- a/src/core/hle/service/ns/errors.h
+++ b/src/core/hle/service/ns/ns_results.h
diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h
new file mode 100644
index 000000000..38421b0f4
--- /dev/null
+++ b/src/core/hle/service/ns/ns_types.h
@@ -0,0 +1,111 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+#include "common/uuid.h"
+#include "core/file_sys/romfs_factory.h"
+
+namespace Service::NS {
+
+enum class ApplicationRecordType : u8 {
+ Installing = 2,
+ Installed = 3,
+ GameCardNotInserted = 5,
+ Archived = 11,
+ GameCard = 16,
+};
+
+enum class ApplicationControlSource : u8 {
+ CacheOnly = 0,
+ Storage = 1,
+ StorageOnly = 2,
+};
+
+enum class BackgroundNetworkUpdateState : u8 {
+ None,
+ InProgress,
+ Ready,
+};
+
+struct ApplicationRecord {
+ u64 application_id;
+ ApplicationRecordType type;
+ u8 unknown;
+ INSERT_PADDING_BYTES_NOINIT(0x6);
+ u8 unknown2;
+ INSERT_PADDING_BYTES_NOINIT(0x7);
+};
+static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size.");
+
+/// ApplicationView
+struct ApplicationView {
+ u64 application_id; ///< ApplicationId.
+ u32 unk; ///< Unknown.
+ u32 flags; ///< Flags.
+ std::array<u8, 0x10> unk_x10; ///< Unknown.
+ u32 unk_x20; ///< Unknown.
+ u16 unk_x24; ///< Unknown.
+ std::array<u8, 0x2> unk_x26; ///< Unknown.
+ std::array<u8, 0x8> unk_x28; ///< Unknown.
+ std::array<u8, 0x10> unk_x30; ///< Unknown.
+ u32 unk_x40; ///< Unknown.
+ u8 unk_x44; ///< Unknown.
+ std::array<u8, 0xb> unk_x45; ///< Unknown.
+};
+static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size.");
+
+struct ApplicationRightsOnClient {
+ u64 application_id;
+ Common::UUID uid;
+ u8 flags;
+ u8 flags2;
+ INSERT_PADDING_BYTES_NOINIT(0x6);
+};
+static_assert(sizeof(ApplicationRightsOnClient) == 0x20,
+ "ApplicationRightsOnClient has incorrect size.");
+
+/// NsPromotionInfo
+struct PromotionInfo {
+ u64 start_timestamp; ///< POSIX timestamp for the promotion start.
+ u64 end_timestamp; ///< POSIX timestamp for the promotion end.
+ s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds
+ ///< ({end_timestamp - current_time} converted to nanoseconds).
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear:
+ ///< remaining_time is set.
+ INSERT_PADDING_BYTES_NOINIT(0x3);
+};
+static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size.");
+
+/// NsApplicationViewWithPromotionInfo
+struct ApplicationViewWithPromotionInfo {
+ ApplicationView view; ///< \ref NsApplicationView
+ PromotionInfo promotion; ///< \ref NsPromotionInfo
+};
+static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70,
+ "ApplicationViewWithPromotionInfo has incorrect size.");
+
+struct ApplicationOccupiedSizeEntity {
+ FileSys::StorageId storage_id;
+ u64 app_size;
+ u64 patch_size;
+ u64 aoc_size;
+};
+static_assert(sizeof(ApplicationOccupiedSizeEntity) == 0x20,
+ "ApplicationOccupiedSizeEntity has incorrect size.");
+
+struct ApplicationOccupiedSize {
+ std::array<ApplicationOccupiedSizeEntity, 4> entities;
+};
+static_assert(sizeof(ApplicationOccupiedSize) == 0x80,
+ "ApplicationOccupiedSize has incorrect size.");
+
+struct ContentPath {
+ u8 file_system_proxy_type;
+ u64 program_id;
+};
+static_assert(sizeof(ContentPath) == 0x10, "ContentPath has incorrect size.");
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp
deleted file mode 100644
index ce0ee30e0..000000000
--- a/src/core/hle/service/ns/pdm_qry.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <memory>
-
-#include "common/logging/log.h"
-#include "common/uuid.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/pdm_qry.h"
-#include "core/hle/service/service.h"
-
-namespace Service::NS {
-
-PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "QueryAppletEvent"},
- {1, nullptr, "QueryPlayStatistics"},
- {2, nullptr, "QueryPlayStatisticsByUserAccountId"},
- {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"},
- {4, nullptr, "QueryPlayStatisticsByApplicationId"},
- {5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"},
- {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"},
- {7, nullptr, "QueryLastPlayTimeV0"},
- {8, nullptr, "QueryPlayEvent"},
- {9, nullptr, "GetAvailablePlayEventRange"},
- {10, nullptr, "QueryAccountEvent"},
- {11, nullptr, "QueryAccountPlayEvent"},
- {12, nullptr, "GetAvailableAccountPlayEventRange"},
- {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"},
- {14, nullptr, "QueryRecentlyPlayedApplication"},
- {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
- {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
- {17, nullptr, "QueryLastPlayTime"},
- {18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
- {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-PDM_QRY::~PDM_QRY() = default;
-
-void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto unknown = rp.Pop<bool>();
- rp.Pop<u8>(); // Padding
- const auto application_id = rp.Pop<u64>();
- const auto user_account_uid = rp.PopRaw<Common::UUID>();
-
- // TODO(German77): Read statistics of the game
- PlayStatistics statistics{
- .application_id = application_id,
- .total_launches = 1,
- };
-
- LOG_WARNING(Service_NS,
- "(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}",
- unknown, application_id, user_account_uid.RawString());
-
- IPC::ResponseBuilder rb{ctx, 12};
- rb.Push(ResultSuccess);
- rb.PushRaw(statistics);
-}
-
-} // namespace Service::NS
diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp
index 46268be95..23cf05005 100644
--- a/src/core/hle/service/ns/iplatform_service_manager.cpp
+++ b/src/core/hle/service/ns/platform_service_manager.cpp
@@ -18,9 +18,9 @@
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_memory.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
+#include "core/hle/service/ns/platform_service_manager.h"
namespace Service::NS {
@@ -37,11 +37,6 @@ constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf
constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};
constexpr FontRegion EMPTY_REGION{0, 0};
-enum class LoadState : u32 {
- Loading = 0,
- Done = 1,
-};
-
static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output,
std::size_t& offset) {
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
@@ -138,13 +133,13 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
: ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"},
- {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"},
- {2, &IPlatformServiceManager::GetSize, "GetSize"},
- {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
- {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
- {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
- {6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"},
+ {0, D<&IPlatformServiceManager::RequestLoad>, "RequestLoad"},
+ {1, D<&IPlatformServiceManager::GetLoadState>, "GetLoadState"},
+ {2, D<&IPlatformServiceManager::GetSize>, "GetSize"},
+ {3, D<&IPlatformServiceManager::GetSharedMemoryAddressOffset>, "GetSharedMemoryAddressOffset"},
+ {4, D<&IPlatformServiceManager::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
+ {5, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriority"},
+ {6, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriorityForSystem"},
{100, nullptr, "RequestApplicationFunctionAuthorization"},
{101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
{102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
@@ -208,47 +203,33 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
IPlatformServiceManager::~IPlatformServiceManager() = default;
-void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 shared_font_type{rp.Pop<u32>()};
+Result IPlatformServiceManager::RequestLoad(SharedFontType type) {
// Games don't call this so all fonts should be loaded
- LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetLoadState(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(LoadState::Done));
+Result IPlatformServiceManager::GetLoadState(Out<LoadState> out_load_state, SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_load_state = LoadState::Loaded;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(impl->GetSharedFontRegion(font_id).size);
+Result IPlatformServiceManager::GetSize(Out<u32> out_size, SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_size = impl->GetSharedFontRegion(static_cast<size_t>(type)).size;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedMemoryAddressOffset(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset);
+Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset,
+ SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_shared_memory_offset = impl->GetSharedFontRegion(static_cast<size_t>(type)).offset;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
+Result IPlatformServiceManager::GetSharedMemoryNativeHandle(
+ OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) {
// Map backing memory for the font data
LOG_DEBUG(Service_NS, "called");
@@ -256,50 +237,37 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx
std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),
impl->shared_font->size());
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(&kernel.GetFontSharedMem());
+ // FIXME: this shouldn't belong to the kernel
+ *out_shared_memory_native_handle = &kernel.GetFontSharedMem();
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) {
+Result IPlatformServiceManager::GetSharedFontInOrderOfPriority(
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, Out<bool> out_fonts_are_loaded,
+ Out<u32> out_font_count, Set::LanguageCode language_code) {
+ LOG_DEBUG(Service_NS, "called, language_code={:#x}", language_code);
+
// The maximum number of elements that can be returned is 6. Regardless of the available fonts
// or buffer size.
- constexpr std::size_t MaxElementCount = 6;
- IPC::RequestParser rp{ctx};
- const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
- const std::size_t font_codes_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0));
- const std::size_t font_offsets_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1));
- const std::size_t font_sizes_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2));
- LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
-
- IPC::ResponseBuilder rb{ctx, 4};
- std::vector<u32> font_codes;
- std::vector<u32> font_offsets;
- std::vector<u32> font_sizes;
+ constexpr size_t MaxElementCount = 6;
// TODO(ogniK): Have actual priority order
- for (std::size_t i = 0; i < impl->shared_font_regions.size(); i++) {
- font_codes.push_back(static_cast<u32>(i));
- auto region = impl->GetSharedFontRegion(i);
- font_offsets.push_back(region.offset);
- font_sizes.push_back(region.size);
- }
+ const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(),
+ out_font_sizes.size(), impl->shared_font_regions.size()});
- // Resize buffers if game requests smaller size output
- font_codes.resize(std::min(font_codes.size(), font_codes_count));
- font_offsets.resize(std::min(font_offsets.size(), font_offsets_count));
- font_sizes.resize(std::min(font_sizes.size(), font_sizes_count));
+ for (size_t i = 0; i < max_size; i++) {
+ auto region = impl->GetSharedFontRegion(i);
- ctx.WriteBuffer(font_codes, 0);
- ctx.WriteBuffer(font_offsets, 1);
- ctx.WriteBuffer(font_sizes, 2);
+ out_font_codes[i] = static_cast<u32>(i);
+ out_font_offsets[i] = region.offset;
+ out_font_sizes[i] = region.size;
+ }
- rb.Push(ResultSuccess);
- rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded
- rb.Push<u32>(static_cast<u32>(font_codes.size()));
+ *out_fonts_are_loaded = true;
+ *out_font_count = static_cast<u32>(max_size);
+ R_SUCCEED();
}
} // namespace Service::NS
diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/platform_service_manager.h
index 03071e02b..b82c385a6 100644
--- a/src/core/hle/service/ns/iplatform_service_manager.h
+++ b/src/core/hle/service/ns/platform_service_manager.h
@@ -5,7 +5,9 @@
#include <memory>
#include <vector>
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings_types.h"
namespace Service {
@@ -23,6 +25,20 @@ enum class FontArchives : u64 {
ChineseSimple = 0x0100000000000814,
};
+enum class SharedFontType : u32 {
+ JapanUSEuropeStandard = 0,
+ ChineseSimplified = 1,
+ ExtendedChineseSimplified = 2,
+ ChineseTraditional = 3,
+ KoreanHangul = 4,
+ NintendoExtended = 5,
+};
+
+enum class LoadState : u32 {
+ Loading = 0,
+ Loaded = 1,
+};
+
constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"),
@@ -42,12 +58,17 @@ public:
~IPlatformServiceManager() override;
private:
- void RequestLoad(HLERequestContext& ctx);
- void GetLoadState(HLERequestContext& ctx);
- void GetSize(HLERequestContext& ctx);
- void GetSharedMemoryAddressOffset(HLERequestContext& ctx);
- void GetSharedMemoryNativeHandle(HLERequestContext& ctx);
- void GetSharedFontInOrderOfPriority(HLERequestContext& ctx);
+ Result RequestLoad(SharedFontType type);
+ Result GetLoadState(Out<LoadState> out_load_state, SharedFontType type);
+ Result GetSize(Out<u32> out_size, SharedFontType type);
+ Result GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, SharedFontType type);
+ Result GetSharedMemoryNativeHandle(
+ OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle);
+ Result GetSharedFontInOrderOfPriority(OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes,
+ Out<bool> out_fonts_are_loaded, Out<u32> out_font_count,
+ Set::LanguageCode language_code);
struct Impl;
std::unique_ptr<Impl> impl;
diff --git a/src/core/hle/service/ns/query_service.cpp b/src/core/hle/service/ns/query_service.cpp
new file mode 100644
index 000000000..946b7fa23
--- /dev/null
+++ b/src/core/hle/service/ns/query_service.cpp
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/logging/log.h"
+#include "common/uuid.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/query_service.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "QueryAppletEvent"},
+ {1, nullptr, "QueryPlayStatistics"},
+ {2, nullptr, "QueryPlayStatisticsByUserAccountId"},
+ {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"},
+ {4, nullptr, "QueryPlayStatisticsByApplicationId"},
+ {5, D<&IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId>, "QueryPlayStatisticsByApplicationIdAndUserAccountId"},
+ {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"},
+ {7, nullptr, "QueryLastPlayTimeV0"},
+ {8, nullptr, "QueryPlayEvent"},
+ {9, nullptr, "GetAvailablePlayEventRange"},
+ {10, nullptr, "QueryAccountEvent"},
+ {11, nullptr, "QueryAccountPlayEvent"},
+ {12, nullptr, "GetAvailableAccountPlayEventRange"},
+ {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"},
+ {14, nullptr, "QueryRecentlyPlayedApplication"},
+ {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
+ {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
+ {17, nullptr, "QueryLastPlayTime"},
+ {18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
+ {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IQueryService::~IQueryService() = default;
+
+Result IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId(
+ Out<PlayStatistics> out_play_statistics, bool unknown, Common::UUID account_id,
+ u64 application_id) {
+ // TODO(German77): Read statistics of the game
+ *out_play_statistics = {
+ .application_id = application_id,
+ .total_launches = 1,
+ };
+
+ LOG_WARNING(Service_NS, "(STUBBED) called. unknown={}. application_id={:016X}, account_id={}",
+ unknown, application_id, account_id.FormattedString());
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/pdm_qry.h b/src/core/hle/service/ns/query_service.h
index c98e01660..6cdbfa277 100644
--- a/src/core/hle/service/ns/pdm_qry.h
+++ b/src/core/hle/service/ns/query_service.h
@@ -3,6 +3,8 @@
#pragma once
+#include "common/uuid.h"
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::NS {
@@ -20,13 +22,15 @@ struct PlayStatistics {
};
static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
-class PDM_QRY final : public ServiceFramework<PDM_QRY> {
+class IQueryService final : public ServiceFramework<IQueryService> {
public:
- explicit PDM_QRY(Core::System& system_);
- ~PDM_QRY() override;
+ explicit IQueryService(Core::System& system_);
+ ~IQueryService() override;
private:
- void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx);
+ Result QueryPlayStatisticsByApplicationIdAndUserAccountId(
+ Out<PlayStatistics> out_play_statistics, bool unknown, Common::UUID account_id,
+ u64 application_id);
};
} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp
new file mode 100644
index 000000000..9b2ca94a4
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp
@@ -0,0 +1,122 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/vfs/vfs.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_results.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+#include "core/hle/service/set/settings_server.h"
+
+namespace Service::NS {
+
+IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
+ Core::System& system_)
+ : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
+ {1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
+ {2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
+ {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+ {4, nullptr, "SelectApplicationDesiredLanguage"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
+ OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source, u64 application_id) {
+ LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
+ application_control_source, application_id);
+
+ const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ const auto control = pm.GetControlMetadata();
+ const auto size = out_buffer.size();
+
+ const auto icon_size = control.second ? control.second->GetSize() : 0;
+ const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
+
+ if (size < total_size) {
+ LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
+ size);
+ R_THROW(ResultUnknown);
+ }
+
+ if (control.first != nullptr) {
+ const auto bytes = control.first->GetRawBytes();
+ std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
+ } else {
+ LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
+ application_id);
+ std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
+ }
+
+ if (control.second != nullptr) {
+ control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size);
+ } else {
+ LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
+ }
+
+ *out_actual_size = static_cast<u32>(total_size);
+ R_SUCCEED();
+}
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
+ Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
+ LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages);
+
+ // Get language code from settings
+ const auto language_code =
+ Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
+
+ // Convert to application language, get priority list
+ const auto application_language = ConvertToApplicationLanguage(language_code);
+ if (application_language == std::nullopt) {
+ LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
+ language_code);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+ const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
+ if (!priority_list) {
+ LOG_ERROR(Service_NS,
+ "Could not find application language priorities! application_language={}",
+ *application_language);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+
+ // Try to find a valid language.
+ for (const auto lang : *priority_list) {
+ const auto supported_flag = GetSupportedLanguageFlag(lang);
+ if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
+ *out_desired_language = lang;
+ R_SUCCEED();
+ }
+ }
+
+ LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
+ supported_languages);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+}
+
+Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode(
+ Out<u64> out_language_code, ApplicationLanguage application_language) {
+ const auto language_code = ConvertToLanguageCode(application_language);
+ if (language_code == std::nullopt) {
+ LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+
+ *out_language_code = static_cast<u64>(*language_code);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.h b/src/core/hle/service/ns/read_only_application_control_data_interface.h
new file mode 100644
index 000000000..ac099435a
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_control_data_interface.h
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IReadOnlyApplicationControlDataInterface final
+ : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
+public:
+ explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
+ ~IReadOnlyApplicationControlDataInterface() override;
+
+public:
+ Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source,
+ u64 application_id);
+ Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
+ u32 supported_languages);
+ Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
+ ApplicationLanguage application_language);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_record_interface.cpp b/src/core/hle/service/ns/read_only_application_record_interface.cpp
new file mode 100644
index 000000000..816a1e1dc
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_record_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/read_only_application_record_interface.h"
+
+namespace Service::NS {
+
+IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
+ : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"},
+ {1, nullptr, "NotifyApplicationFailure"},
+ {2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>,
+ "IsDataCorruptedResult"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
+
+Result IReadOnlyApplicationRecordInterface::HasApplicationRecord(
+ Out<bool> out_has_application_record, u64 program_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:016X}", program_id);
+ *out_has_application_record = true;
+ R_SUCCEED();
+}
+
+Result IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(
+ Out<bool> out_is_data_corrupted_result, Result result) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
+ *out_is_data_corrupted_result = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_record_interface.h b/src/core/hle/service/ns/read_only_application_record_interface.h
new file mode 100644
index 000000000..d06e8f5e6
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_record_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IReadOnlyApplicationRecordInterface final
+ : public ServiceFramework<IReadOnlyApplicationRecordInterface> {
+public:
+ explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
+ ~IReadOnlyApplicationRecordInterface() override;
+
+private:
+ Result HasApplicationRecord(Out<bool> out_has_application_record, u64 program_id);
+ Result IsDataCorruptedResult(Out<bool> out_is_data_corrupted_result, Result result);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/service_getter_interface.cpp b/src/core/hle/service/ns/service_getter_interface.cpp
new file mode 100644
index 000000000..1a3dd7166
--- /dev/null
+++ b/src/core/hle/service/ns/service_getter_interface.cpp
@@ -0,0 +1,120 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/account_proxy_interface.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/application_version_interface.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/document_interface.h"
+#include "core/hle/service/ns/download_task_interface.h"
+#include "core/hle/service/ns/dynamic_rights_interface.h"
+#include "core/hle/service/ns/ecommerce_interface.h"
+#include "core/hle/service/ns/factory_reset_interface.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+#include "core/hle/service/ns/read_only_application_record_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
+
+namespace Service::NS {
+
+IServiceGetterInterface::IServiceGetterInterface(Core::System& system_, const char* name)
+ : ServiceFramework{system_, name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {7988, D<&IServiceGetterInterface::GetDynamicRightsInterface>, "GetDynamicRightsInterface"},
+ {7989, D<&IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
+ {7991, D<&IServiceGetterInterface::GetReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
+ {7992, D<&IServiceGetterInterface::GetECommerceInterface>, "GetECommerceInterface"},
+ {7993, D<&IServiceGetterInterface::GetApplicationVersionInterface>, "GetApplicationVersionInterface"},
+ {7994, D<&IServiceGetterInterface::GetFactoryResetInterface>, "GetFactoryResetInterface"},
+ {7995, D<&IServiceGetterInterface::GetAccountProxyInterface>, "GetAccountProxyInterface"},
+ {7996, D<&IServiceGetterInterface::GetApplicationManagerInterface>, "GetApplicationManagerInterface"},
+ {7997, D<&IServiceGetterInterface::GetDownloadTaskInterface>, "GetDownloadTaskInterface"},
+ {7998, D<&IServiceGetterInterface::GetContentManagementInterface>, "GetContentManagementInterface"},
+ {7999, D<&IServiceGetterInterface::GetDocumentInterface>, "GetDocumentInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IServiceGetterInterface::~IServiceGetterInterface() = default;
+
+Result IServiceGetterInterface::GetDynamicRightsInterface(
+ Out<SharedPointer<IDynamicRightsInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDynamicRightsInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface(
+ Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IReadOnlyApplicationControlDataInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface(
+ Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IReadOnlyApplicationRecordInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetECommerceInterface(
+ Out<SharedPointer<IECommerceInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IECommerceInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetApplicationVersionInterface(
+ Out<SharedPointer<IApplicationVersionInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IApplicationVersionInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetFactoryResetInterface(
+ Out<SharedPointer<IFactoryResetInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IFactoryResetInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetAccountProxyInterface(
+ Out<SharedPointer<IAccountProxyInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IAccountProxyInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetApplicationManagerInterface(
+ Out<SharedPointer<IApplicationManagerInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IApplicationManagerInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetDownloadTaskInterface(
+ Out<SharedPointer<IDownloadTaskInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDownloadTaskInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetContentManagementInterface(
+ Out<SharedPointer<IContentManagementInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IContentManagementInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetDocumentInterface(
+ Out<SharedPointer<IDocumentInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDocumentInterface>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/service_getter_interface.h b/src/core/hle/service/ns/service_getter_interface.h
new file mode 100644
index 000000000..bbc18d444
--- /dev/null
+++ b/src/core/hle/service/ns/service_getter_interface.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDynamicRightsInterface;
+class IReadOnlyApplicationControlDataInterface;
+class IReadOnlyApplicationRecordInterface;
+class IECommerceInterface;
+class IApplicationVersionInterface;
+class IFactoryResetInterface;
+class IAccountProxyInterface;
+class IApplicationManagerInterface;
+class IDownloadTaskInterface;
+class IContentManagementInterface;
+class IDocumentInterface;
+
+class IServiceGetterInterface : public ServiceFramework<IServiceGetterInterface> {
+public:
+ explicit IServiceGetterInterface(Core::System& system_, const char* name);
+ ~IServiceGetterInterface() override;
+
+public:
+ Result GetDynamicRightsInterface(Out<SharedPointer<IDynamicRightsInterface>> out_interface);
+ Result GetReadOnlyApplicationControlDataInterface(
+ Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface);
+ Result GetReadOnlyApplicationRecordInterface(
+ Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface);
+ Result GetECommerceInterface(Out<SharedPointer<IECommerceInterface>> out_interface);
+ Result GetApplicationVersionInterface(
+ Out<SharedPointer<IApplicationVersionInterface>> out_interface);
+ Result GetFactoryResetInterface(Out<SharedPointer<IFactoryResetInterface>> out_interface);
+ Result GetAccountProxyInterface(Out<SharedPointer<IAccountProxyInterface>> out_interface);
+ Result GetApplicationManagerInterface(
+ Out<SharedPointer<IApplicationManagerInterface>> out_interface);
+ Result GetDownloadTaskInterface(Out<SharedPointer<IDownloadTaskInterface>> out_interface);
+ Result GetContentManagementInterface(
+ Out<SharedPointer<IContentManagementInterface>> out_interface);
+ Result GetDocumentInterface(Out<SharedPointer<IDocumentInterface>> out_interface);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_control.cpp b/src/core/hle/service/ns/system_update_control.cpp
new file mode 100644
index 000000000..f5f5cfd90
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_control.cpp
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/system_update_control.h"
+
+namespace Service::NS {
+
+ISystemUpdateControl::ISystemUpdateControl(Core::System& system_)
+ : ServiceFramework{system_, "ISystemUpdateControl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "HasDownloaded"},
+ {1, nullptr, "RequestCheckLatestUpdate"},
+ {2, nullptr, "RequestDownloadLatestUpdate"},
+ {3, nullptr, "GetDownloadProgress"},
+ {4, nullptr, "ApplyDownloadedUpdate"},
+ {5, nullptr, "RequestPrepareCardUpdate"},
+ {6, nullptr, "GetPrepareCardUpdateProgress"},
+ {7, nullptr, "HasPreparedCardUpdate"},
+ {8, nullptr, "ApplyCardUpdate"},
+ {9, nullptr, "GetDownloadedEulaDataSize"},
+ {10, nullptr, "GetDownloadedEulaData"},
+ {11, nullptr, "SetupCardUpdate"},
+ {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
+ {13, nullptr, "GetPreparedCardUpdateEulaData"},
+ {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
+ {15, nullptr, "HasReceived"},
+ {16, nullptr, "RequestReceiveSystemUpdate"},
+ {17, nullptr, "GetReceiveProgress"},
+ {18, nullptr, "ApplyReceivedUpdate"},
+ {19, nullptr, "GetReceivedEulaDataSize"},
+ {20, nullptr, "GetReceivedEulaData"},
+ {21, nullptr, "SetupToReceiveSystemUpdate"},
+ {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemUpdateControl::~ISystemUpdateControl() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_control.h b/src/core/hle/service/ns/system_update_control.h
new file mode 100644
index 000000000..a30a09000
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_control.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
+public:
+ explicit ISystemUpdateControl(Core::System& system_);
+ ~ISystemUpdateControl() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_interface.cpp b/src/core/hle/service/ns/system_update_interface.cpp
new file mode 100644
index 000000000..7e22ca3db
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.cpp
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/system_update_control.h"
+#include "core/hle/service/ns/system_update_interface.h"
+
+namespace Service::NS {
+
+ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_)
+ : ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"},
+ update_notification_event{service_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"},
+ {1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"},
+ {2, nullptr, "NotifyExFatDriverRequired"},
+ {3, nullptr, "ClearExFatDriverStatusForDebug"},
+ {4, nullptr, "RequestBackgroundNetworkUpdate"},
+ {5, nullptr, "NotifyBackgroundNetworkUpdate"},
+ {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
+ {9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"},
+ {10, nullptr, "NotifySystemUpdateForContentDelivery"},
+ {11, nullptr, "PrepareShutdown"},
+ {12, nullptr, "Unknown12"},
+ {13, nullptr, "Unknown13"},
+ {14, nullptr, "Unknown14"},
+ {15, nullptr, "Unknown15"},
+ {16, nullptr, "DestroySystemUpdateTask"},
+ {17, nullptr, "RequestSendSystemUpdate"},
+ {18, nullptr, "GetSendSystemUpdateProgress"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemUpdateInterface::~ISystemUpdateInterface() = default;
+
+Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState(
+ Out<BackgroundNetworkUpdateState> out_background_network_update_state) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_background_network_update_state = BackgroundNetworkUpdateState::None;
+ R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::OpenSystemUpdateControl(
+ Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_system_update_control = std::make_shared<ISystemUpdateControl>(system);
+ R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = update_notification_event.GetHandle();
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_interface.h b/src/core/hle/service/ns/system_update_interface.h
new file mode 100644
index 000000000..36a2880ec
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.h
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::NS {
+
+class ISystemUpdateControl;
+
+class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> {
+public:
+ explicit ISystemUpdateInterface(Core::System& system_);
+ ~ISystemUpdateInterface() override;
+
+private:
+ Result GetBackgroundNetworkUpdateState(
+ Out<BackgroundNetworkUpdateState> out_background_network_update_state);
+ Result OpenSystemUpdateControl(
+ Out<SharedPointer<ISystemUpdateControl>> out_system_update_control);
+ Result GetSystemUpdateNotificationEventForContentDelivery(
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Event update_notification_event;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.cpp b/src/core/hle/service/ns/vulnerability_manager_interface.cpp
new file mode 100644
index 000000000..69c21fb89
--- /dev/null
+++ b/src/core/hle/service/ns/vulnerability_manager_interface.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/vulnerability_manager_interface.h"
+
+namespace Service::NS {
+
+IVulnerabilityManagerInterface::IVulnerabilityManagerInterface(Core::System& system_)
+ : ServiceFramework{system_, "ns:vm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1200, D<&IVulnerabilityManagerInterface::NeedsUpdateVulnerability>, "NeedsUpdateVulnerability"},
+ {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
+ {1202, nullptr, "GetSafeSystemVersion"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IVulnerabilityManagerInterface::~IVulnerabilityManagerInterface() = default;
+
+Result IVulnerabilityManagerInterface::NeedsUpdateVulnerability(
+ Out<bool> out_needs_update_vulnerability) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_needs_update_vulnerability = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.h b/src/core/hle/service/ns/vulnerability_manager_interface.h
new file mode 100644
index 000000000..c689cf7ec
--- /dev/null
+++ b/src/core/hle/service/ns/vulnerability_manager_interface.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IVulnerabilityManagerInterface final
+ : public ServiceFramework<IVulnerabilityManagerInterface> {
+public:
+ explicit IVulnerabilityManagerInterface(Core::System& system_);
+ ~IVulnerabilityManagerInterface() override;
+
+private:
+ Result NeedsUpdateVulnerability(Out<bool> out_needs_update_vulnerability);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 250d01de3..0265d55f2 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -92,11 +92,11 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a
bool must_unmark_fail = !is_allocation;
const u32 event_id = params.value.raw;
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (must_unmark_fail) {
events[event_id].fails = 0;
}
- });
+ };
const u32 fence_id = static_cast<u32>(params.fence.id);
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index cb256e5b4..03eb507b9 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {
module.service_context.CloseEvent(event);
}
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
+void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
auto module = std::make_shared<Module>(system);
const auto NvdrvInterfaceFactoryForApplication = [&, module] {
@@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);
server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
- nvnflinger.SetNVDrvInstance(module);
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index c594f0e5e..b76f81e59 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,13 +10,11 @@
#include <span>
#include <string>
#include <unordered_map>
-#include <vector>
#include "common/common_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvnflinger/ui/fence.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -27,10 +25,6 @@ namespace Kernel {
class KEvent;
}
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
namespace Service::Nvidia {
namespace NvCore {
@@ -99,7 +93,6 @@ public:
private:
friend class EventInterface;
- friend class Service::Nvnflinger::Nvnflinger;
/// Manages syncpoints on the host
NvCore::Container container;
@@ -118,6 +111,6 @@ private:
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
};
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
+void LoopProcess(Core::System& system);
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index ffe72f281..258970fd5 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -154,10 +154,10 @@ void NVDRV::Close(HLERequestContext& ctx) {
void NVDRV::Initialize(HLERequestContext& ctx) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
- SCOPE_EXIT({
+ SCOPE_EXIT {
rb.Push(ResultSuccess);
rb.PushEnum(NvResult::Success);
- });
+ };
if (is_initialized) {
// No need to initialize again
@@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char*
}
NVDRV::~NVDRV() {
- auto& container = nvdrv->GetContainer();
- container.CloseSession(session_id);
+ if (is_initialized) {
+ auto& container = nvdrv->GetContainer();
+ container.CloseSession(session_id);
+ }
}
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h
index f2195ae1e..c72f92597 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.h
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.h
@@ -16,6 +16,10 @@ public:
explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name);
~NVDRV() override;
+ std::shared_ptr<Module> GetModule() const {
+ return nvdrv;
+ }
+
private:
void Open(HLERequestContext& ctx);
void Ioctl1(HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h
index 179938192..124accb94 100644
--- a/src/core/hle/service/nvnflinger/binder.h
+++ b/src/core/hle/service/nvnflinger/binder.h
@@ -20,29 +20,12 @@ class HLERequestContext;
namespace Service::android {
-enum class TransactionId {
- RequestBuffer = 1,
- SetBufferCount = 2,
- DequeueBuffer = 3,
- DetachBuffer = 4,
- DetachNextBuffer = 5,
- AttachBuffer = 6,
- QueueBuffer = 7,
- CancelBuffer = 8,
- Query = 9,
- Connect = 10,
- Disconnect = 11,
- AllocateBuffers = 13,
- SetPreallocatedBuffer = 14,
- GetBufferHistory = 17,
-};
-
class IBinder {
public:
virtual ~IBinder() = default;
- virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data,
- std::span<u8> parcel_reply) = 0;
- virtual Kernel::KReadableEvent& GetNativeHandle() = 0;
+ virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) = 0;
+ virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0;
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
index cf151ea3a..123507123 100644
--- a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
@@ -12,7 +12,7 @@
namespace Service::android {
-BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_)
+BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_)
: ConsumerBase{std::move(consumer_)} {}
Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h
index e0c6b3604..9f95c9280 100644
--- a/src/core/hle/service/nvnflinger/buffer_item_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h
@@ -19,7 +19,7 @@ class BufferItem;
class BufferItemConsumer final : public ConsumerBase {
public:
- explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer);
+ explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer);
Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
bool wait_for_fence = true);
Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index bbe8e06d4..3bc23aa97 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -4,12 +4,13 @@
// Parts of this implementation were based on:
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
+#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
+#include "core/hle/service/nvnflinger/parcel.h"
#include "core/hle/service/nvnflinger/producer_listener.h"
-#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
namespace Service::android {
@@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
return Status::NoError;
}
+void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data,
+ std::span<u8> parcel_reply, u32 flags) {
+ // Values used by BnGraphicBufferConsumer onTransact
+ enum class TransactionId {
+ AcquireBuffer = 1,
+ DetachBuffer = 2,
+ AttachBuffer = 3,
+ ReleaseBuffer = 4,
+ ConsumerConnect = 5,
+ ConsumerDisconnect = 6,
+ GetReleasedBuffers = 7,
+ SetDefaultBufferSize = 8,
+ SetDefaultMaxBufferCount = 9,
+ DisableAsyncBuffer = 10,
+ SetMaxAcquiredBufferCount = 11,
+ SetConsumerName = 12,
+ SetDefaultBufferFormat = 13,
+ SetConsumerUsageBits = 14,
+ SetTransformHint = 15,
+ GetSidebandStream = 16,
+ Unknown18 = 18,
+ Unknown20 = 20,
+ };
+
+ Status status{Status::NoError};
+ InputParcel parcel_in{parcel_data};
+ OutputParcel parcel_out{};
+
+ switch (static_cast<TransactionId>(code)) {
+ case TransactionId::AcquireBuffer: {
+ BufferItem item;
+ const s64 present_when = parcel_in.Read<s64>();
+
+ status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when});
+
+ // TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer>
+ // parcel_out.WriteFlattened(item);
+ UNREACHABLE();
+ }
+ case TransactionId::ReleaseBuffer: {
+ const s32 slot = parcel_in.Read<s32>();
+ const u64 frame_number = parcel_in.Read<u64>();
+ const auto release_fence = parcel_in.ReadFlattened<Fence>();
+
+ status = ReleaseBuffer(slot, frame_number, release_fence);
+
+ break;
+ }
+ case TransactionId::GetReleasedBuffers: {
+ u64 slot_mask = 0;
+
+ status = GetReleasedBuffers(&slot_mask);
+
+ parcel_out.Write(slot_mask);
+ break;
+ }
+ default:
+ ASSERT_MSG(false, "called, code={} flags={}", code, flags);
+ break;
+ }
+
+ parcel_out.Write(status);
+
+ const auto serialized = parcel_out.Serialize();
+ std::memcpy(parcel_reply.data(), serialized.data(),
+ std::min(parcel_reply.size(), serialized.size()));
+}
+
+Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) {
+ ASSERT_MSG(false, "called, type_id={}", type_id);
+ return nullptr;
+}
+
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
index 0a61e8dbd..a9226f1c3 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
@@ -10,6 +10,7 @@
#include <memory>
#include "common/common_types.h"
+#include "core/hle/service/nvnflinger/binder.h"
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/status.h"
@@ -19,10 +20,10 @@ class BufferItem;
class BufferQueueCore;
class IConsumerListener;
-class BufferQueueConsumer final {
+class BufferQueueConsumer final : public IBinder {
public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
- ~BufferQueueConsumer();
+ ~BufferQueueConsumer() override;
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
@@ -30,6 +31,11 @@ public:
Status Disconnect();
Status GetReleasedBuffers(u64* out_slot_mask);
+ void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) override;
+
+ Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
+
private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
index ec83beb9b..9e5091eeb 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
@@ -6,12 +6,9 @@
#include "common/assert.h"
#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
@@ -19,7 +16,6 @@
#include "core/hle/service/nvnflinger/parcel.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
#include "core/hle/service/nvnflinger/window.h"
-#include "core/hle/service/vi/vi.h"
namespace Service::android {
@@ -807,13 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
return Status::NoError;
}
-void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data,
- std::span<u8> parcel_reply) {
+void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
+ std::span<u8> parcel_reply, u32 flags) {
+ // Values used by BnGraphicBufferProducer onTransact
+ enum class TransactionId {
+ RequestBuffer = 1,
+ SetBufferCount = 2,
+ DequeueBuffer = 3,
+ DetachBuffer = 4,
+ DetachNextBuffer = 5,
+ AttachBuffer = 6,
+ QueueBuffer = 7,
+ CancelBuffer = 8,
+ Query = 9,
+ Connect = 10,
+ Disconnect = 11,
+ AllocateBuffers = 13,
+ SetPreallocatedBuffer = 14,
+ GetBufferHistory = 17,
+ };
+
Status status{Status::NoError};
InputParcel parcel_in{parcel_data};
OutputParcel parcel_out{};
- switch (code) {
+ switch (static_cast<TransactionId>(code)) {
case TransactionId::Connect: {
const auto enable_listener = parcel_in.Read<bool>();
const auto api = parcel_in.Read<NativeWindowApi>();
@@ -923,8 +937,8 @@ void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<cons
std::min(parcel_reply.size(), serialized.size()));
}
-Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() {
- return buffer_wait_event->GetReadableEvent();
+Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) {
+ return &buffer_wait_event->GetReadableEvent();
}
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
index 4682b0f84..048523514 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
@@ -45,12 +45,12 @@ public:
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
Service::Nvidia::NvCore::NvMap& nvmap_);
- ~BufferQueueProducer();
+ ~BufferQueueProducer() override;
- void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data,
- std::span<u8> parcel_reply) override;
+ void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) override;
- Kernel::KReadableEvent& GetNativeHandle() override;
+ Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
public:
Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp
index 1059e72bf..e360ebfd8 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.cpp
+++ b/src/core/hle/service/nvnflinger/consumer_base.cpp
@@ -14,7 +14,7 @@
namespace Service::android {
-ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
+ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_)
: consumer{std::move(consumer_)} {}
ConsumerBase::~ConsumerBase() {
diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h
index ea3e9e97a..b29c16f86 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.h
+++ b/src/core/hle/service/nvnflinger/consumer_base.h
@@ -27,7 +27,7 @@ public:
void Abandon();
protected:
- explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
+ explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_);
~ConsumerBase() override;
void OnFrameAvailable(const BufferItem& item) override;
@@ -54,7 +54,7 @@ protected:
bool is_abandoned{};
- std::unique_ptr<BufferQueueConsumer> consumer;
+ std::shared_ptr<BufferQueueConsumer> consumer;
mutable std::mutex mutex;
};
diff --git a/src/core/hle/service/nvnflinger/display.h b/src/core/hle/service/nvnflinger/display.h
new file mode 100644
index 000000000..f27cbf144
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/display.h
@@ -0,0 +1,55 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <list>
+
+#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
+#include "core/hle/service/nvnflinger/hwc_layer.h"
+
+namespace Service::Nvnflinger {
+
+struct Layer {
+ explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_,
+ s32 consumer_id_)
+ : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_),
+ blending(LayerBlending::None), visible(true) {}
+ ~Layer() {
+ buffer_item_consumer->Abandon();
+ }
+
+ std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer;
+ s32 consumer_id;
+ LayerBlending blending;
+ bool visible;
+};
+
+struct LayerStack {
+ std::list<Layer> layers;
+};
+
+struct Display {
+ explicit Display(u64 id_) {
+ id = id_;
+ }
+
+ Layer* FindLayer(s32 consumer_id) {
+ for (auto& layer : stack.layers) {
+ if (layer.consumer_id == consumer_id) {
+ return &layer;
+ }
+ }
+
+ return nullptr;
+ }
+
+ bool HasLayers() {
+ return !stack.layers.empty();
+ }
+
+ u64 id;
+ LayerStack stack;
+};
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp
index be7eb97a3..02215a786 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.cpp
+++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp
@@ -10,8 +10,6 @@
#include "core/hle/service/nvnflinger/hardware_composer.h"
#include "core/hle/service/nvnflinger/hwc_layer.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
namespace Service::Nvnflinger {
@@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) {
HardwareComposer::HardwareComposer() = default;
HardwareComposer::~HardwareComposer() = default;
-u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
+u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
Nvidia::Devices::nvdisp_disp0& nvdisp) {
boost::container::small_vector<HwcLayer, 2> composition_stack;
@@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
bool has_acquired_buffer{};
// Acquire all necessary framebuffers.
- for (size_t i = 0; i < display.GetNumLayers(); i++) {
- auto& layer = display.GetLayer(i);
- auto layer_id = layer.GetLayerId();
+ for (auto& layer : display.stack.layers) {
+ auto consumer_id = layer.consumer_id;
// Try to fetch the framebuffer (either new or stale).
- const auto result = this->CacheFramebufferLocked(layer, layer_id);
+ const auto result = this->CacheFramebufferLocked(layer, consumer_id);
// If we failed, skip this layer.
if (result == CacheStatus::NoBufferAvailable) {
@@ -73,24 +70,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
has_acquired_buffer = true;
}
- const auto& buffer = m_framebuffers[layer_id];
+ const auto& buffer = m_framebuffers[consumer_id];
const auto& item = buffer.item;
const auto& igbp_buffer = *item.graphic_buffer;
// TODO: get proper Z-index from layer
- composition_stack.emplace_back(HwcLayer{
- .buffer_handle = igbp_buffer.BufferId(),
- .offset = igbp_buffer.Offset(),
- .format = igbp_buffer.ExternalFormat(),
- .width = igbp_buffer.Width(),
- .height = igbp_buffer.Height(),
- .stride = igbp_buffer.Stride(),
- .z_index = 0,
- .blending = layer.GetBlending(),
- .transform = static_cast<android::BufferTransformFlags>(item.transform),
- .crop_rect = item.crop,
- .acquire_fence = item.fence,
- });
+ if (layer.visible) {
+ composition_stack.emplace_back(HwcLayer{
+ .buffer_handle = igbp_buffer.BufferId(),
+ .offset = igbp_buffer.Offset(),
+ .format = igbp_buffer.ExternalFormat(),
+ .width = igbp_buffer.Width(),
+ .height = igbp_buffer.Height(),
+ .stride = igbp_buffer.Stride(),
+ .z_index = 0,
+ .blending = layer.blending,
+ .transform = static_cast<android::BufferTransformFlags>(item.transform),
+ .crop_rect = item.crop,
+ .acquire_fence = item.fence,
+ });
+ }
// We need to compose again either before this frame is supposed to
// be released, or exactly on the vsync period it should be released.
@@ -138,7 +137,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
if (auto* layer = display.FindLayer(layer_id); layer != nullptr) {
// TODO: support release fence
// This is needed to prevent screen tearing
- layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
+ layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
framebuffer.is_acquired = false;
}
}
@@ -146,26 +145,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
return frame_advance;
}
-void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) {
- // Check if we are tracking a slot with this layer_id.
- const auto it = m_framebuffers.find(layer_id);
+void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) {
+ // Check if we are tracking a slot with this consumer_id.
+ const auto it = m_framebuffers.find(consumer_id);
if (it == m_framebuffers.end()) {
return;
}
// Try to release the buffer item.
- auto* const layer = display.FindLayer(layer_id);
+ auto* const layer = display.FindLayer(consumer_id);
if (layer && it->second.is_acquired) {
- layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence());
+ layer->buffer_item_consumer->ReleaseBuffer(it->second.item, android::Fence::NoFence());
}
// Erase the slot.
m_framebuffers.erase(it);
}
-bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) {
+bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer) {
// Attempt the update.
- const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false);
+ const auto status = layer.buffer_item_consumer->AcquireBuffer(&framebuffer.item, {}, false);
if (status != android::Status::NoError) {
return false;
}
@@ -178,10 +177,10 @@ bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer
return true;
}
-HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer,
- LayerId layer_id) {
+HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(Layer& layer,
+ ConsumerId consumer_id) {
// Check if this framebuffer is already present.
- const auto it = m_framebuffers.find(layer_id);
+ const auto it = m_framebuffers.find(consumer_id);
if (it != m_framebuffers.end()) {
// If it's currently still acquired, we are done.
if (it->second.is_acquired) {
@@ -203,7 +202,7 @@ HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer
if (this->TryAcquireFramebufferLocked(layer, framebuffer)) {
// Move the buffer item into a new slot.
- m_framebuffers.emplace(layer_id, std::move(framebuffer));
+ m_framebuffers.emplace(consumer_id, std::move(framebuffer));
// We succeeded.
return CacheStatus::BufferAcquired;
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h
index 28392c512..c5b830468 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.h
+++ b/src/core/hle/service/nvnflinger/hardware_composer.h
@@ -3,35 +3,29 @@
#pragma once
-#include <memory>
#include <boost/container/flat_map.hpp>
#include "core/hle/service/nvnflinger/buffer_item.h"
+#include "core/hle/service/nvnflinger/display.h"
namespace Service::Nvidia::Devices {
class nvdisp_disp0;
}
-namespace Service::VI {
-class Display;
-class Layer;
-} // namespace Service::VI
-
namespace Service::Nvnflinger {
-using LayerId = u64;
+using ConsumerId = s32;
class HardwareComposer {
public:
explicit HardwareComposer();
~HardwareComposer();
- u32 ComposeLocked(f32* out_speed_scale, VI::Display& display,
+ u32 ComposeLocked(f32* out_speed_scale, Display& display,
Nvidia::Devices::nvdisp_disp0& nvdisp);
- void RemoveLayerLocked(VI::Display& display, LayerId layer_id);
+ void RemoveLayerLocked(Display& display, ConsumerId consumer_id);
private:
- // TODO: do we want to track frame number in vi instead?
u64 m_frame_number{0};
private:
@@ -49,11 +43,11 @@ private:
CachedBufferReused,
};
- boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{};
+ boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{};
private:
- bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer);
- CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id);
+ bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer);
+ CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id);
};
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/vi/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
index ba0317245..8629a2e89 100644
--- a/src/core/hle/service/vi/hos_binder_driver.cpp
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
@@ -3,13 +3,16 @@
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/nvnflinger/binder.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
-#include "core/hle/service/vi/hos_binder_driver.h"
-namespace Service::VI {
+namespace Service::Nvnflinger {
-IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server)
- : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server) {
+IHOSBinderDriver::IHOSBinderDriver(Core::System& system_,
+ std::shared_ptr<HosBinderDriverServer> server,
+ std::shared_ptr<SurfaceFlinger> surface_flinger)
+ : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server),
+ m_surface_flinger(surface_flinger) {
static const FunctionInfo functions[] = {
{0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"},
{1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"},
@@ -21,13 +24,18 @@ IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderD
IHOSBinderDriver::~IHOSBinderDriver() = default;
-Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id,
+Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id,
InBuffer<BufferAttr_HipcMapAlias> parcel_data,
OutBuffer<BufferAttr_HipcMapAlias> parcel_reply,
u32 flags) {
LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id,
flags);
- m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply);
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_SUCCEED_IF(binder == nullptr);
+
+ binder->Transact(transaction_id, parcel_data, parcel_reply, flags);
+
R_SUCCEED();
}
@@ -39,15 +47,20 @@ Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {
Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id,
OutCopyHandle<Kernel::KReadableEvent> out_handle) {
LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id);
- *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle();
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_UNLESS(binder != nullptr, ResultUnknown);
+
+ *out_handle = binder->GetNativeHandle(type_id);
+
R_SUCCEED();
}
-Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id,
+Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id,
InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply,
u32 flags) {
R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags));
}
-} // namespace Service::VI
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/vi/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h
index ed6e8cdbe..b7fb07bd2 100644
--- a/src/core/hle/service/vi/hos_binder_driver.h
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h
@@ -2,29 +2,45 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
-#include "core/hle/service/nvnflinger/binder.h"
#include "core/hle/service/service.h"
-namespace Service::VI {
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Nvnflinger {
+
+class HosBinderDriverServer;
+class SurfaceFlinger;
class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
public:
- explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server);
+ explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server,
+ std::shared_ptr<SurfaceFlinger> surface_flinger);
~IHOSBinderDriver() override;
+ std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() {
+ return m_surface_flinger;
+ }
+
+ std::shared_ptr<HosBinderDriverServer> GetServer() {
+ return m_server;
+ }
+
private:
- Result TransactParcel(s32 binder_id, android::TransactionId transaction_id,
+ Result TransactParcel(s32 binder_id, u32 transaction_id,
InBuffer<BufferAttr_HipcMapAlias> parcel_data,
OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags);
Result AdjustRefcount(s32 binder_id, s32 addval, s32 type);
Result GetNativeHandle(s32 binder_id, u32 type_id,
OutCopyHandle<Kernel::KReadableEvent> out_handle);
- Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id,
+ Result TransactParcelAuto(s32 binder_id, u32 transaction_id,
InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags);
private:
- Nvnflinger::HosBinderDriverServer& m_server;
+ const std::shared_ptr<HosBinderDriverServer> m_server;
+ const std::shared_ptr<SurfaceFlinger> m_surface_flinger;
};
-} // namespace Service::VI
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
index b86a79ec9..29addda44 100644
--- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
@@ -8,26 +8,30 @@
namespace Service::Nvnflinger {
-HosBinderDriverServer::HosBinderDriverServer(Core::System& system_)
- : service_context(system_, "HosBinderDriverServer") {}
+HosBinderDriverServer::HosBinderDriverServer() = default;
+HosBinderDriverServer::~HosBinderDriverServer() = default;
-HosBinderDriverServer::~HosBinderDriverServer() {}
-
-u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) {
+s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) {
std::scoped_lock lk{lock};
last_id++;
- producers[last_id] = std::move(binder);
+ binders[last_id] = std::move(binder);
return last_id;
}
-android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) {
+void HosBinderDriverServer::UnregisterBinder(s32 binder_id) {
+ std::scoped_lock lk{lock};
+
+ binders.erase(binder_id);
+}
+
+std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const {
std::scoped_lock lk{lock};
- if (auto search = producers.find(id); search != producers.end()) {
- return search->second.get();
+ if (auto search = binders.find(id); search != binders.end()) {
+ return search->second;
}
return {};
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
index 58bb9469a..d72b50833 100644
--- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
@@ -8,7 +8,6 @@
#include <unordered_map>
#include "common/common_types.h"
-#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvnflinger/binder.h"
namespace Core {
@@ -19,19 +18,18 @@ namespace Service::Nvnflinger {
class HosBinderDriverServer final {
public:
- explicit HosBinderDriverServer(Core::System& system_);
+ explicit HosBinderDriverServer();
~HosBinderDriverServer();
- u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder);
+ s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder);
+ void UnregisterBinder(s32 binder_id);
- android::IBinder* TryGetProducer(u64 id);
+ std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const;
private:
- KernelHelpers::ServiceContext service_context;
-
- std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers;
- std::mutex lock;
- u64 last_id{};
+ std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders;
+ mutable std::mutex lock;
+ s32 last_id{};
};
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index 687ccc9f9..9e3b68b8a 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -1,335 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
-#include <algorithm>
-#include <optional>
-
-#include "common/assert.h"
-#include "common/logging/log.h"
-#include "common/microprofile.h"
-#include "common/scope_exit.h"
-#include "common/settings.h"
-#include "common/thread.h"
#include "core/core.h"
-#include "core/core_timing.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_core.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/hardware_composer.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-#include "core/hle/service/vi/vi_results.h"
-#include "video_core/gpu.h"
-#include "video_core/host1x/host1x.h"
-#include "video_core/host1x/syncpoint_manager.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/server_manager.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::Nvnflinger {
-constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
-
-void Nvnflinger::SplitVSync(std::stop_token stop_token) {
- system.RegisterHostThread();
- std::string name = "VSyncThread";
- MicroProfileOnThreadCreate(name.c_str());
-
- // Cleanup
- SCOPE_EXIT({ MicroProfileOnThreadExit(); });
-
- Common::SetCurrentThreadName(name.c_str());
- Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
-
- while (!stop_token.stop_requested()) {
- vsync_signal.Wait();
-
- const auto lock_guard = Lock();
-
- if (!is_abandoned) {
- Compose();
- }
- }
-}
-
-Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_)
- : system(system_), service_context(system_, "nvnflinger"),
- hos_binder_driver_server(hos_binder_driver_server_) {
- displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system);
- displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system);
- displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system);
- displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system);
- displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system);
- guard = std::make_shared<std::mutex>();
-
- // Schedule the screen composition events
- multi_composition_event = Core::Timing::CreateEvent(
- "ScreenComposition",
- [this](s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- vsync_signal.Set();
- return std::chrono::nanoseconds(GetNextTicks());
- });
-
- single_composition_event = Core::Timing::CreateEvent(
- "ScreenComposition",
- [this](s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto lock_guard = Lock();
- Compose();
-
- return std::chrono::nanoseconds(GetNextTicks());
- });
-
- if (system.IsMulticore()) {
- system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
- vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
- } else {
- system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
- }
-}
-
-Nvnflinger::~Nvnflinger() {
- if (system.IsMulticore()) {
- system.CoreTiming().UnscheduleEvent(multi_composition_event);
- vsync_thread.request_stop();
- vsync_signal.Set();
- } else {
- system.CoreTiming().UnscheduleEvent(single_composition_event);
- }
-
- ShutdownLayers();
-
- if (nvdrv) {
- nvdrv->Close(disp_fd);
- }
-}
-
-void Nvnflinger::ShutdownLayers() {
- // Abandon consumers.
- {
- const auto lock_guard = Lock();
- for (auto& display : displays) {
- display.Abandon();
- }
-
- is_abandoned = true;
- }
-
- // Join the vsync thread, if it exists.
- vsync_thread = {};
-}
-
-void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
- nvdrv = std::move(instance);
- disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
-}
-
-std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) {
- const auto lock_guard = Lock();
-
- LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name);
-
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetName() == name; });
-
- if (itr == displays.end()) {
- return std::nullopt;
- }
-
- return itr->GetID();
-}
-
-bool Nvnflinger::CloseDisplay(u64 display_id) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return false;
- }
-
- display->Reset();
-
- return true;
-}
-
-std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return std::nullopt;
- }
-
- const u64 layer_id = next_layer_id++;
- CreateLayerAtId(*display, layer_id, blending);
- return layer_id;
-}
-
-void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) {
- const auto buffer_id = next_buffer_queue_id++;
- display.CreateLayer(layer_id, buffer_id, nvdrv->container);
- display.FindLayer(layer_id)->SetBlending(blending);
-}
-
-bool Nvnflinger::OpenLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- return layer->Open();
- }
- }
-
- return false;
-}
-
-bool Nvnflinger::CloseLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- return layer->Close();
- }
- }
-
- return false;
-}
-
-void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- layer->SetVisibility(visible);
- }
- }
-}
-
-void Nvnflinger::DestroyLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- display.DestroyLayer(layer_id);
- }
-}
-
-std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
- const auto lock_guard = Lock();
- const auto* const layer = FindLayer(display_id, layer_id);
-
- if (layer == nullptr) {
- return std::nullopt;
- }
-
- return layer->GetBinderId();
-}
-
-Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return VI::ResultNotFound;
- }
-
- *out_vsync_event = display->GetVSyncEvent();
- return ResultSuccess;
-}
-
-VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetID() == display_id; });
-
- if (itr == displays.end()) {
- return nullptr;
- }
-
- return &*itr;
-}
-
-const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const {
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetID() == display_id; });
-
- if (itr == displays.end()) {
- return nullptr;
- }
-
- return &*itr;
-}
-
-VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) {
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return nullptr;
- }
-
- return display->FindLayer(layer_id);
-}
-
-void Nvnflinger::Compose() {
- for (auto& display : displays) {
- // Trigger vsync for this display at the end of drawing
- SCOPE_EXIT({ display.SignalVSyncEvent(); });
-
- // Don't do anything for displays without layers.
- if (!display.HasLayers()) {
- continue;
- }
-
- if (!system.IsPoweredOn()) {
- return; // We are likely shutting down
- }
-
- auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd);
- ASSERT(nvdisp);
-
- swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp);
- }
-}
-
-s64 Nvnflinger::GetNextTicks() const {
- const auto& settings = Settings::values;
- auto speed_scale = 1.f;
- if (settings.use_multi_core.GetValue()) {
- if (settings.use_speed_limit.GetValue()) {
- // Scales the speed based on speed_limit setting on MC. SC is handled by
- // SpeedLimiter::DoSpeedLimiting.
- speed_scale = 100.f / settings.speed_limit.GetValue();
- } else {
- // Run at unlocked framerate.
- speed_scale = 0.01f;
- }
- }
-
- // Adjust by speed limit determined during composition.
- speed_scale /= compose_speed_scale;
-
- if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
- // Run at intended presentation rate during video playback.
- speed_scale = 1.f;
- }
-
- const f32 effective_fps = 60.f / static_cast<f32>(swap_interval);
- return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
-}
-
-FbShareBufferManager& Nvnflinger::GetSystemBufferManager() {
- const auto lock_guard = Lock();
-
- if (!system_buffer_manager) {
- system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv);
- }
+void LoopProcess(Core::System& system) {
+ const auto binder_server = std::make_shared<HosBinderDriverServer>();
+ const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server);
- return *system_buffer_manager;
+ auto server_manager = std::make_unique<ServerManager>(system);
+ server_manager->RegisterNamedService(
+ "dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger));
+ ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index 4cf4f069d..5c41f3013 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -3,170 +3,12 @@
#pragma once
-#include <list>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <thread>
-#include <vector>
-
-#include "common/common_types.h"
-#include "common/polyfill_thread.h"
-#include "common/thread.h"
-#include "core/hle/result.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/nvnflinger/hwc_layer.h"
-
-namespace Common {
-class Event;
-} // namespace Common
-
-namespace Core::Timing {
-class CoreTiming;
-struct EventType;
-} // namespace Core::Timing
-
-namespace Kernel {
-class KReadableEvent;
-} // namespace Kernel
-
-namespace Service::Nvidia {
-class Module;
-} // namespace Service::Nvidia
-
-namespace Service::VI {
-class Display;
-class Layer;
-} // namespace Service::VI
-
-namespace Service::android {
-class BufferQueueCore;
-class BufferQueueProducer;
-} // namespace Service::android
+namespace Core {
+class System;
+}
namespace Service::Nvnflinger {
-class FbShareBufferManager;
-class HardwareComposer;
-class HosBinderDriverServer;
-
-class Nvnflinger final {
-public:
- explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
- ~Nvnflinger();
-
- void ShutdownLayers();
-
- /// Sets the NVDrv module instance to use to send buffers to the GPU.
- void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
-
- /// Opens the specified display and returns the ID.
- ///
- /// If an invalid display name is provided, then an empty optional is returned.
- [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
-
- /// Closes the specified display by its ID.
- ///
- /// Returns false if an invalid display ID is provided.
- [[nodiscard]] bool CloseDisplay(u64 display_id);
-
- /// Creates a layer on the specified display and returns the layer ID.
- ///
- /// If an invalid display ID is specified, then an empty optional is returned.
- [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id,
- LayerBlending blending = LayerBlending::None);
-
- /// Opens a layer on all displays for the given layer ID.
- bool OpenLayer(u64 layer_id);
-
- /// Closes a layer on all displays for the given layer ID.
- bool CloseLayer(u64 layer_id);
-
- /// Makes a layer visible on all displays for the given layer ID.
- void SetLayerVisibility(u64 layer_id, bool visible);
-
- /// Destroys the given layer ID.
- void DestroyLayer(u64 layer_id);
-
- /// Finds the buffer queue ID of the specified layer in the specified display.
- ///
- /// If an invalid display ID or layer ID is provided, then an empty optional is returned.
- [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id);
-
- /// Gets the vsync event for the specified display.
- ///
- /// If an invalid display ID is provided, then VI::ResultNotFound is returned.
- /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
- [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id);
-
- /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
- /// finished.
- void Compose();
-
- [[nodiscard]] s64 GetNextTicks() const;
-
- FbShareBufferManager& GetSystemBufferManager();
-
-private:
- struct Layer {
- std::unique_ptr<android::BufferQueueCore> core;
- std::unique_ptr<android::BufferQueueProducer> producer;
- };
-
- friend class FbShareBufferManager;
-
-private:
- [[nodiscard]] std::unique_lock<std::mutex> Lock() const {
- return std::unique_lock{*guard};
- }
-
- /// Finds the display identified by the specified ID.
- [[nodiscard]] VI::Display* FindDisplay(u64 display_id);
-
- /// Finds the display identified by the specified ID.
- [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
-
- /// Finds the layer identified by the specified ID in the desired display.
- [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
-
- /// Creates a layer with the specified layer ID in the desired display.
- void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending);
-
- void SplitVSync(std::stop_token stop_token);
-
- std::shared_ptr<Nvidia::Module> nvdrv;
- s32 disp_fd;
-
- std::list<VI::Display> displays;
-
- /// Id to use for the next layer that is created, this counter is shared among all displays.
- u64 next_layer_id = 1;
- /// Id to use for the next buffer queue that is created, this counter is shared among all
- /// layers.
- u32 next_buffer_queue_id = 1;
-
- s32 swap_interval = 1;
- f32 compose_speed_scale = 1.0f;
-
- bool is_abandoned = false;
-
- /// Event that handles screen composition.
- std::shared_ptr<Core::Timing::EventType> multi_composition_event;
- std::shared_ptr<Core::Timing::EventType> single_composition_event;
-
- std::unique_ptr<FbShareBufferManager> system_buffer_manager;
-
- std::shared_ptr<std::mutex> guard;
-
- Core::System& system;
-
- Common::Event vsync_signal;
-
- std::jthread vsync_thread;
-
- KernelHelpers::ServiceContext service_context;
-
- HosBinderDriverServer& hos_binder_driver_server;
-};
+void LoopProcess(Core::System& system);
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp
new file mode 100644
index 000000000..41a705717
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp
@@ -0,0 +1,124 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
+#include "core/hle/service/nvdrv/nvdrv_interface.h"
+#include "core/hle/service/nvnflinger/display.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/sm/sm.h"
+
+#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
+#include "core/hle/service/nvnflinger/buffer_queue_core.h"
+#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
+
+namespace Service::Nvnflinger {
+
+SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server)
+ : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") {
+ nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
+ disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
+}
+
+SurfaceFlinger::~SurfaceFlinger() {
+ nvdrv->Close(disp_fd);
+}
+
+void SurfaceFlinger::AddDisplay(u64 display_id) {
+ m_displays.emplace_back(display_id);
+}
+
+void SurfaceFlinger::RemoveDisplay(u64 display_id) {
+ std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; });
+}
+
+bool SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale,
+ u64 display_id) {
+ auto* const display = this->FindDisplay(display_id);
+ if (!display || !display->HasLayers()) {
+ return false;
+ }
+
+ *out_swap_interval =
+ m_composer.ComposeLocked(out_compose_speed_scale, *display,
+ *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd));
+ return true;
+}
+
+void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) {
+ auto* const display = this->FindDisplay(display_id);
+ auto binder = std::static_pointer_cast<android::BufferQueueConsumer>(
+ m_server.TryGetBinder(consumer_binder_id));
+
+ if (!display || !binder) {
+ return;
+ }
+
+ auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder));
+ buffer_item_consumer->Connect(false);
+
+ display->stack.layers.emplace_back(std::move(buffer_item_consumer), consumer_binder_id);
+}
+
+void SurfaceFlinger::RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id) {
+ auto* const display = this->FindDisplay(display_id);
+ if (!display) {
+ return;
+ }
+
+ m_composer.RemoveLayerLocked(*display, consumer_binder_id);
+ std::erase_if(display->stack.layers,
+ [&](auto& layer) { return layer.consumer_id == consumer_binder_id; });
+}
+
+void SurfaceFlinger::SetLayerVisibility(s32 consumer_binder_id, bool visible) {
+ if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
+ layer->visible = visible;
+ return;
+ }
+}
+
+void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) {
+ if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
+ layer->blending = blending;
+ return;
+ }
+}
+
+Display* SurfaceFlinger::FindDisplay(u64 display_id) {
+ for (auto& display : m_displays) {
+ if (display.id == display_id) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+}
+
+Layer* SurfaceFlinger::FindLayer(s32 consumer_binder_id) {
+ for (auto& display : m_displays) {
+ if (auto* layer = display.FindLayer(consumer_binder_id); layer != nullptr) {
+ return layer;
+ }
+ }
+
+ return nullptr;
+}
+
+void SurfaceFlinger::CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id) {
+ auto& nvmap = nvdrv->GetContainer().GetNvMapFile();
+ auto core = std::make_shared<android::BufferQueueCore>();
+ auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap);
+ auto consumer = std::make_shared<android::BufferQueueConsumer>(core);
+
+ *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer));
+ *out_producer_binder_id = m_server.RegisterBinder(std::move(producer));
+}
+
+void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) {
+ m_server.UnregisterBinder(producer_binder_id);
+ m_server.UnregisterBinder(consumer_binder_id);
+}
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.h b/src/core/hle/service/nvnflinger/surface_flinger.h
new file mode 100644
index 000000000..d8c53fbda
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/surface_flinger.h
@@ -0,0 +1,65 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <vector>
+
+#include "common/common_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/nvnflinger/hardware_composer.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Nvidia {
+class Module;
+}
+
+// TODO: ISurfaceComposer
+// TODO: ISurfaceComposerClient
+
+namespace Service::Nvnflinger {
+
+struct Display;
+class HosBinderDriverServer;
+enum class LayerBlending : u32;
+struct Layer;
+
+class SurfaceFlinger {
+public:
+ explicit SurfaceFlinger(Core::System& system, HosBinderDriverServer& server);
+ ~SurfaceFlinger();
+
+ void AddDisplay(u64 display_id);
+ void RemoveDisplay(u64 display_id);
+ bool ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id);
+
+ void AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id);
+ void RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id);
+
+ void SetLayerVisibility(s32 consumer_binder_id, bool visible);
+ void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending);
+
+private:
+ Display* FindDisplay(u64 display_id);
+ Layer* FindLayer(s32 consumer_binder_id);
+
+public:
+ // TODO: these don't belong here
+ void CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id);
+ void DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id);
+
+private:
+ Core::System& m_system;
+ HosBinderDriverServer& m_server;
+ KernelHelpers::ServiceContext m_context;
+
+ std::vector<Display> m_displays;
+ std::shared_ptr<Nvidia::Module> nvdrv;
+ s32 disp_fd;
+ HardwareComposer m_composer;
+};
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp
index 24b85cc61..9a0adb295 100644
--- a/src/core/hle/service/psc/time/static.cpp
+++ b/src/core/hle/service/psc/time/static.cpp
@@ -144,7 +144,9 @@ Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
Out<bool> out_is_enabled) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled);
+ };
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
@@ -180,7 +182,9 @@ Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient);
+ };
*out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
@@ -189,7 +193,9 @@ Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> o
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Out<SteadyClockTimePoint> out_time_point) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point);
+ };
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
@@ -200,7 +206,9 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
Out<s64> out_time, const SystemClockContext& context) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time);
+ };
R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
@@ -219,8 +227,9 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
}
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) {
- SCOPE_EXIT(
- { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot);
+ };
SystemClockContext user_context{};
R_TRY(m_user_system_clock.GetContext(user_context));
@@ -234,11 +243,11 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType t
Result StaticService::GetClockSnapshotFromSystemClockContext(
TimeType type, OutClockSnapshot out_snapshot, const SystemClockContext& user_context,
const SystemClockContext& network_context) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. type={} user_context={} network_context={} out_snapshot={}", type,
user_context, network_context, *out_snapshot);
- });
+ };
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
}
@@ -246,9 +255,9 @@ Result StaticService::GetClockSnapshotFromSystemClockContext(
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
InClockSnapshot a,
InClockSnapshot b) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
- });
+ };
auto diff_s =
std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset);
@@ -276,7 +285,9 @@ Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64>
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
InClockSnapshot b) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time);
+ };
s64 time_s{};
auto res =
diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp
index 948610a2b..78dcf532c 100644
--- a/src/core/hle/service/psc/time/steady_clock.cpp
+++ b/src/core/hle/service/psc/time/steady_clock.cpp
@@ -29,7 +29,9 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
}
Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -38,7 +40,9 @@ Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point
}
Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -59,7 +63,9 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
}
Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -68,7 +74,9 @@ Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
}
Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -78,7 +86,9 @@ Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
}
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -88,8 +98,9 @@ Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
}
Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) {
- SCOPE_EXIT(
- { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp
index b4e9264d8..9f841d8e0 100644
--- a/src/core/hle/service/psc/time/system_clock.cpp
+++ b/src/core/hle/service/psc/time/system_clock.cpp
@@ -26,7 +26,9 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
}
Result SystemClock::GetCurrentTime(Out<s64> out_time) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -45,7 +47,9 @@ Result SystemClock::SetCurrentTime(s64 time) {
}
Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context);
+ };
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp
index 2f80030a4..9e0674f27 100644
--- a/src/core/hle/service/psc/time/time_zone_service.cpp
+++ b/src/core/hle/service/psc/time/time_zone_service.cpp
@@ -37,7 +37,9 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
}
Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name);
+ };
R_RETURN(m_time_zone.GetLocationName(*out_location_name));
}
@@ -50,7 +52,9 @@ Result TimeZoneService::SetDeviceLocationName(const LocationName& location_name)
}
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count);
+ };
R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));
}
@@ -69,17 +73,19 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, const LocationName& l
}
Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) {
- SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
+ SCOPE_EXIT {
+ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version);
+ };
R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));
}
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
*out_location_name, *out_time_point);
- });
+ };
R_TRY(m_time_zone.GetLocationName(*out_location_name));
R_RETURN(m_time_zone.GetTimePoint(*out_time_point));
@@ -116,10 +122,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time,
InRule rule) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
- });
+ };
R_RETURN(
m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get()));
@@ -128,10 +134,10 @@ Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info,
s64 time) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
- });
+ };
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));
}
@@ -139,11 +145,11 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
const CalendarTime& calendar_time, InRule rule) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
calendar_time, *out_count, out_times[0], out_times[1]);
- });
+ };
R_RETURN(
m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule));
@@ -152,11 +158,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
const CalendarTime& calendar_time) {
- SCOPE_EXIT({
+ SCOPE_EXIT {
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
calendar_time, *out_count, out_times[0], out_times[1]);
- });
+ };
R_RETURN(
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time));
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp
index 8c7f94c8c..0b41bbcb9 100644
--- a/src/core/hle/service/server_manager.cpp
+++ b/src/core/hle/service/server_manager.cpp
@@ -177,10 +177,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name,
Kernel::KPort::Register(m_system.Kernel(), port);
// Ensure that our reference to the port is closed if we fail to register it.
- SCOPE_EXIT({
+ SCOPE_EXIT {
port->GetClientPort().Close();
port->GetServerPort().Close();
- });
+ };
// Register the object name with the kernel.
R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()),
@@ -237,7 +237,9 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre
}
Result ServerManager::LoopProcess() {
- SCOPE_EXIT({ m_stopped.Set(); });
+ SCOPE_EXIT {
+ m_stopped.Set();
+ };
R_RETURN(this->LoopProcessImpl());
}
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index fbdf217ba..ce5e3b5b4 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -7,68 +7,10 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/hle/ipc.h"
-#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/k_server_port.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/acc/acc.h"
-#include "core/hle/service/am/am.h"
-#include "core/hle/service/aoc/aoc_u.h"
-#include "core/hle/service/apm/apm.h"
-#include "core/hle/service/audio/audio.h"
-#include "core/hle/service/bcat/bcat.h"
-#include "core/hle/service/bpc/bpc.h"
-#include "core/hle/service/btdrv/btdrv.h"
-#include "core/hle/service/btm/btm.h"
-#include "core/hle/service/caps/caps.h"
-#include "core/hle/service/erpt/erpt.h"
-#include "core/hle/service/es/es.h"
-#include "core/hle/service/eupld/eupld.h"
-#include "core/hle/service/fatal/fatal.h"
-#include "core/hle/service/fgm/fgm.h"
-#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/friend/friend.h"
-#include "core/hle/service/glue/glue.h"
-#include "core/hle/service/grc/grc.h"
-#include "core/hle/service/hid/hid.h"
#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/jit/jit.h"
-#include "core/hle/service/lbl/lbl.h"
-#include "core/hle/service/ldn/ldn.h"
-#include "core/hle/service/ldr/ldr.h"
-#include "core/hle/service/lm/lm.h"
-#include "core/hle/service/mig/mig.h"
-#include "core/hle/service/mii/mii.h"
-#include "core/hle/service/mm/mm_u.h"
-#include "core/hle/service/mnpp/mnpp_app.h"
-#include "core/hle/service/ncm/ncm.h"
-#include "core/hle/service/nfc/nfc.h"
-#include "core/hle/service/nfp/nfp.h"
-#include "core/hle/service/ngc/ngc.h"
-#include "core/hle/service/nifm/nifm.h"
-#include "core/hle/service/nim/nim.h"
-#include "core/hle/service/npns/npns.h"
-#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/olsc/olsc.h"
-#include "core/hle/service/omm/omm.h"
-#include "core/hle/service/pcie/pcie.h"
-#include "core/hle/service/pctl/pctl_module.h"
-#include "core/hle/service/pcv/pcv.h"
-#include "core/hle/service/pm/pm.h"
-#include "core/hle/service/prepo/prepo.h"
-#include "core/hle/service/psc/psc.h"
-#include "core/hle/service/ptm/ptm.h"
-#include "core/hle/service/ro/ro.h"
#include "core/hle/service/service.h"
-#include "core/hle/service/set/settings.h"
#include "core/hle/service/sm/sm.h"
-#include "core/hle/service/sockets/sockets.h"
-#include "core/hle/service/spl/spl_module.h"
-#include "core/hle/service/ssl/ssl.h"
-#include "core/hle/service/usb/usb.h"
-#include "core/hle/service/vi/vi.h"
#include "core/reporter.h"
namespace Service {
@@ -209,82 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
return result;
}
-/// Initialize Services
-Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system)
- : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)},
- nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} {
-
- auto& kernel = system.Kernel();
-
- // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
- // here and pass it into the respective InstallInterfaces functions.
- system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
-
- // clang-format off
- kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach();
- kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("vi", [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach();
-
- kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(*nv_flinger, system); });
- kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); });
- // glue depends on settings and psc, so they must come first
- kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); });
- // clang-format on
-}
-
-Services::~Services() = default;
-
-void Services::KillNVNFlinger() {
- nv_flinger->ShutdownLayers();
-}
-
} // namespace Service
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 22d1343d5..36aae1c79 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -28,11 +28,6 @@ namespace FileSystem {
class FileSystemController;
}
-namespace Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Nvnflinger
-
namespace SM {
class ServiceManager;
}
@@ -236,20 +231,4 @@ private:
}
};
-/**
- * The purpose of this class is to own any objects that need to be shared across the other service
- * implementations. Will be torn down when the global system instance is shutdown.
- */
-class Services final {
-public:
- explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
- ~Services();
-
- void KillNVNFlinger();
-
-private:
- std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server;
- std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger;
-};
-
} // namespace Service
diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp
new file mode 100644
index 000000000..d6c6eff50
--- /dev/null
+++ b/src/core/hle/service/services.cpp
@@ -0,0 +1,136 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/services.h"
+
+#include "core/hle/service/acc/acc.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/aoc/aoc_u.h"
+#include "core/hle/service/apm/apm.h"
+#include "core/hle/service/audio/audio.h"
+#include "core/hle/service/bcat/bcat.h"
+#include "core/hle/service/bpc/bpc.h"
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/btm/btm.h"
+#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/erpt/erpt.h"
+#include "core/hle/service/es/es.h"
+#include "core/hle/service/eupld/eupld.h"
+#include "core/hle/service/fatal/fatal.h"
+#include "core/hle/service/fgm/fgm.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/friend/friend.h"
+#include "core/hle/service/glue/glue.h"
+#include "core/hle/service/grc/grc.h"
+#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/jit/jit.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/ldn/ldn.h"
+#include "core/hle/service/ldr/ldr.h"
+#include "core/hle/service/lm/lm.h"
+#include "core/hle/service/mig/mig.h"
+#include "core/hle/service/mii/mii.h"
+#include "core/hle/service/mm/mm_u.h"
+#include "core/hle/service/mnpp/mnpp_app.h"
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/nfc/nfc.h"
+#include "core/hle/service/nfp/nfp.h"
+#include "core/hle/service/ngc/ngc.h"
+#include "core/hle/service/nifm/nifm.h"
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/npns/npns.h"
+#include "core/hle/service/ns/ns.h"
+#include "core/hle/service/nvdrv/nvdrv.h"
+#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/olsc/olsc.h"
+#include "core/hle/service/omm/omm.h"
+#include "core/hle/service/pcie/pcie.h"
+#include "core/hle/service/pctl/pctl_module.h"
+#include "core/hle/service/pcv/pcv.h"
+#include "core/hle/service/pm/pm.h"
+#include "core/hle/service/prepo/prepo.h"
+#include "core/hle/service/psc/psc.h"
+#include "core/hle/service/ptm/ptm.h"
+#include "core/hle/service/ro/ro.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/sockets/sockets.h"
+#include "core/hle/service/spl/spl_module.h"
+#include "core/hle/service/ssl/ssl.h"
+#include "core/hle/service/usb/usb.h"
+#include "core/hle/service/vi/vi.h"
+
+namespace Service {
+
+Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
+ std::stop_token token) {
+ auto& kernel = system.Kernel();
+
+ system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
+
+ // clang-format off
+ kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach();
+
+ kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nvnflinger", [&] { Nvnflinger::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); });
+ // clang-format on
+}
+
+Services::~Services() = default;
+
+} // namespace Service
diff --git a/src/core/hle/service/services.h b/src/core/hle/service/services.h
new file mode 100644
index 000000000..a99fa1e53
--- /dev/null
+++ b/src/core/hle/service/services.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/polyfill_thread.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service {
+
+/**
+ * The purpose of this class is to own any objects that need to be shared across the other service
+ * implementations. Will be torn down when the global system instance is shutdown.
+ */
+class Services final {
+public:
+ explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
+ std::stop_token token);
+ ~Services();
+};
+
+} // namespace Service
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp
index 78229e30f..6b0bcb536 100644
--- a/src/core/hle/service/vi/application_display_service.cpp
+++ b/src/core/hle/service/vi/application_display_service.cpp
@@ -2,22 +2,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/nvnflinger/parcel.h"
+#include "core/hle/service/os/event.h"
#include "core/hle/service/vi/application_display_service.h"
-#include "core/hle/service/vi/hos_binder_driver.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/manager_display_service.h"
#include "core/hle/service/vi/system_display_service.h"
#include "core/hle/service/vi/vi_results.h"
namespace Service::VI {
-IApplicationDisplayService::IApplicationDisplayService(
- Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server)
- : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger},
- m_hos_binder_driver_server{hos_binder_driver_server} {
-
+IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "IApplicationDisplayService"},
+ m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} {
// clang-format off
static const FunctionInfo functions[] = {
{100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"},
@@ -48,38 +47,41 @@ IApplicationDisplayService::IApplicationDisplayService(
}
IApplicationDisplayService::~IApplicationDisplayService() {
+ for (auto& [display_id, event] : m_display_vsync_events) {
+ m_container->UnlinkVsyncEvent(display_id, &event);
+ }
+ for (const auto layer_id : m_open_layer_ids) {
+ m_container->CloseLayer(layer_id);
+ }
for (const auto layer_id : m_stray_layer_ids) {
- m_nvnflinger.DestroyLayer(layer_id);
+ m_container->DestroyStrayLayer(layer_id);
}
}
Result IApplicationDisplayService::GetRelayService(
- Out<SharedPointer<IHOSBinderDriver>> out_relay_service) {
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) {
LOG_WARNING(Service_VI, "(STUBBED) called");
- *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server);
- R_SUCCEED();
+ R_RETURN(m_container->GetBinderDriver(out_relay_service));
}
Result IApplicationDisplayService::GetSystemDisplayService(
Out<SharedPointer<ISystemDisplayService>> out_system_display_service) {
LOG_WARNING(Service_VI, "(STUBBED) called");
- *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger);
+ *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container);
R_SUCCEED();
}
Result IApplicationDisplayService::GetManagerDisplayService(
Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) {
LOG_WARNING(Service_VI, "(STUBBED) called");
- *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger);
+ *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container);
R_SUCCEED();
}
Result IApplicationDisplayService::GetIndirectDisplayTransactionService(
- Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) {
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) {
LOG_WARNING(Service_VI, "(STUBBED) called");
- *out_indirect_display_transaction_service =
- std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server);
- R_SUCCEED();
+ R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service));
}
Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) {
@@ -89,14 +91,7 @@ Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayN
ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,
"Non-default displays aren't supported yet");
- const auto display_id = m_nvnflinger.OpenDisplay(display_name.data());
- if (!display_id) {
- LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data());
- R_THROW(VI::ResultNotFound);
- }
-
- *out_display_id = *display_id;
- R_SUCCEED();
+ R_RETURN(m_container->OpenDisplay(out_display_id, display_name));
}
Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
@@ -106,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
Result IApplicationDisplayService::CloseDisplay(u64 display_id) {
LOG_DEBUG(Service_VI, "called");
- R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id));
- R_THROW(ResultUnknown);
+ R_RETURN(m_container->CloseDisplay(display_id));
}
Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) {
@@ -168,25 +162,19 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,
LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid);
- const auto display_id = m_nvnflinger.OpenDisplay(display_name.data());
- if (!display_id) {
- LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
- R_THROW(VI::ResultNotFound);
- }
+ u64 display_id;
+ R_TRY(m_container->OpenDisplay(&display_id, display_name));
- const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
- R_THROW(VI::ResultNotFound);
- }
+ s32 producer_binder_id;
+ R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid));
- if (!m_nvnflinger.OpenLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to open layer which was already open");
- R_THROW(VI::ResultOperationFailed);
+ {
+ std::scoped_lock lk{m_lock};
+ m_open_layer_ids.insert(layer_id);
}
android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
+ parcel.WriteInterface(NativeWindow{producer_binder_id});
const auto buffer = parcel.Serialize();
std::memcpy(out_native_window.data(), buffer.data(),
@@ -199,12 +187,13 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,
Result IApplicationDisplayService::CloseLayer(u64 layer_id) {
LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
- if (!m_nvnflinger.CloseLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to close layer which was not open");
- R_THROW(VI::ResultOperationFailed);
+ {
+ std::scoped_lock lk{m_lock};
+ R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound);
+ m_open_layer_ids.erase(layer_id);
}
- R_SUCCEED();
+ R_RETURN(m_container->CloseLayer(layer_id));
}
Result IApplicationDisplayService::CreateStrayLayer(
@@ -212,27 +201,19 @@ Result IApplicationDisplayService::CreateStrayLayer(
u32 flags, u64 display_id) {
LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id);
- const auto layer_id = m_nvnflinger.CreateLayer(display_id);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
- R_THROW(VI::ResultNotFound);
- }
+ s32 producer_binder_id;
+ R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id));
- m_stray_layer_ids.push_back(*layer_id);
- const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
- R_THROW(VI::ResultNotFound);
- }
+ std::scoped_lock lk{m_lock};
+ m_stray_layer_ids.insert(*out_layer_id);
android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
+ parcel.WriteInterface(NativeWindow{producer_binder_id});
const auto buffer = parcel.Serialize();
std::memcpy(out_native_window.data(), buffer.data(),
std::min(out_native_window.size(), buffer.size()));
- *out_layer_id = *layer_id;
*out_size = buffer.size();
R_SUCCEED();
@@ -240,25 +221,27 @@ Result IApplicationDisplayService::CreateStrayLayer(
Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) {
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
- m_nvnflinger.DestroyLayer(layer_id);
- R_SUCCEED();
+
+ {
+ std::scoped_lock lk{m_lock};
+ R_UNLESS(m_stray_layer_ids.contains(layer_id), VI::ResultNotFound);
+ m_stray_layer_ids.erase(layer_id);
+ }
+
+ R_RETURN(m_container->DestroyStrayLayer(layer_id));
}
Result IApplicationDisplayService::GetDisplayVsyncEvent(
OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) {
LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
- const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id);
- if (result != ResultSuccess) {
- if (result == ResultNotFound) {
- LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
- }
+ std::scoped_lock lk{m_lock};
- R_THROW(result);
- }
+ auto [it, created] = m_display_vsync_events.emplace(display_id, m_context);
+ R_UNLESS(created, VI::ResultPermissionDenied);
- R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied);
- m_vsync_event_fetched = true;
+ m_container->LinkVsyncEvent(display_id, &it->second);
+ *out_vsync_event = it->second.GetHandle();
R_SUCCEED();
}
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h
index 5dff4bb31..1bdeb8f84 100644
--- a/src/core/hle/service/vi/application_display_service.h
+++ b/src/core/hle/service/vi/application_display_service.h
@@ -1,7 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <map>
+#include <set>
+
#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/os/event.h"
#include "core/hle/service/service.h"
#include "core/hle/service/vi/vi_types.h"
@@ -9,26 +14,33 @@ namespace Kernel {
class KReadableEvent;
}
+namespace Service::Nvnflinger {
+class IHOSBinderDriver;
+}
+
namespace Service::VI {
-class IHOSBinderDriver;
+class Container;
class IManagerDisplayService;
class ISystemDisplayService;
class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
public:
- IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+ IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container);
~IApplicationDisplayService() override;
-private:
- Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service);
+ std::shared_ptr<Container> GetContainer() const {
+ return m_container;
+ }
+
+public:
+ Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service);
Result GetSystemDisplayService(
Out<SharedPointer<ISystemDisplayService>> out_system_display_service);
Result GetManagerDisplayService(
Out<SharedPointer<IManagerDisplayService>> out_manager_display_service);
Result GetIndirectDisplayTransactionService(
- Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service);
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service);
Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name);
Result OpenDefaultDisplay(Out<u64> out_display_id);
Result CloseDisplay(u64 display_id);
@@ -56,9 +68,13 @@ private:
s64 width, s64 height);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
- Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server;
- std::vector<u64> m_stray_layer_ids;
+ const std::shared_ptr<Container> m_container;
+
+ KernelHelpers::ServiceContext m_context;
+ std::mutex m_lock{};
+ std::set<u64> m_open_layer_ids{};
+ std::set<u64> m_stray_layer_ids{};
+ std::map<u64, Event> m_display_vsync_events{};
bool m_vsync_event_fetched{false};
};
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp
index 7af7f062c..7f35a048d 100644
--- a/src/core/hle/service/vi/application_root_service.cpp
+++ b/src/core/hle/service/vi/application_root_service.cpp
@@ -4,17 +4,16 @@
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/vi/application_display_service.h"
#include "core/hle/service/vi/application_root_service.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/service_creator.h"
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/vi/vi_types.h"
namespace Service::VI {
-IApplicationRootService::IApplicationRootService(
- Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server)
- : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{
- hos_binder_driver_server} {
+IApplicationRootService::IApplicationRootService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} {
static const FunctionInfo functions[] = {
{0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"},
{1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -27,8 +26,8 @@ IApplicationRootService::~IApplicationRootService() = default;
Result IApplicationRootService::GetDisplayService(
Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger,
- m_hos_binder_driver_server, Permission::User, policy));
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::User, policy));
}
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h
index 9dbf28cb4..15aa4483d 100644
--- a/src/core/hle/service/vi/application_root_service.h
+++ b/src/core/hle/service/vi/application_root_service.h
@@ -10,20 +10,15 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
+class Container;
class IApplicationDisplayService;
enum class Policy : u32;
class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {
public:
- explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+ explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container);
~IApplicationRootService() override;
private:
@@ -32,8 +27,7 @@ private:
Policy policy);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
- Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server;
+ const std::shared_ptr<Container> m_container;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp
new file mode 100644
index 000000000..c8ce4fca0
--- /dev/null
+++ b/src/core/hle/service/vi/conductor.cpp
@@ -0,0 +1,114 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hle/service/vi/conductor.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/display_list.h"
+#include "core/hle/service/vi/vsync_manager.h"
+
+constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60};
+
+namespace Service::VI {
+
+Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays)
+ : m_system(system), m_container(container) {
+ displays.ForEachDisplay([&](Display& display) {
+ m_vsync_managers.insert({display.GetId(), VsyncManager{}});
+ });
+
+ if (system.IsMulticore()) {
+ m_event = Core::Timing::CreateEvent(
+ "ScreenComposition",
+ [this](s64 time,
+ std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
+ m_signal.Set();
+ return std::chrono::nanoseconds(this->GetNextTicks());
+ });
+
+ system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
+ m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); });
+ } else {
+ m_event = Core::Timing::CreateEvent(
+ "ScreenComposition",
+ [this](s64 time,
+ std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
+ this->ProcessVsync();
+ return std::chrono::nanoseconds(this->GetNextTicks());
+ });
+
+ system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
+ }
+}
+
+Conductor::~Conductor() {
+ m_system.CoreTiming().UnscheduleEvent(m_event);
+
+ if (m_system.IsMulticore()) {
+ m_thread.request_stop();
+ m_signal.Set();
+ }
+}
+
+void Conductor::LinkVsyncEvent(u64 display_id, Event* event) {
+ if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) {
+ it->second.LinkVsyncEvent(event);
+ }
+}
+
+void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) {
+ if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) {
+ it->second.UnlinkVsyncEvent(event);
+ }
+}
+
+void Conductor::ProcessVsync() {
+ for (auto& [display_id, manager] : m_vsync_managers) {
+ m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id);
+ manager.SignalVsync();
+ }
+}
+
+void Conductor::VsyncThread(std::stop_token token) {
+ Common::SetCurrentThreadName("VSyncThread");
+
+ while (!token.stop_requested()) {
+ m_signal.Wait();
+
+ if (m_system.IsShuttingDown()) {
+ return;
+ }
+
+ this->ProcessVsync();
+ }
+}
+
+s64 Conductor::GetNextTicks() const {
+ const auto& settings = Settings::values;
+ auto speed_scale = 1.f;
+ if (settings.use_multi_core.GetValue()) {
+ if (settings.use_speed_limit.GetValue()) {
+ // Scales the speed based on speed_limit setting on MC. SC is handled by
+ // SpeedLimiter::DoSpeedLimiting.
+ speed_scale = 100.f / settings.speed_limit.GetValue();
+ } else {
+ // Run at unlocked framerate.
+ speed_scale = 0.01f;
+ }
+ }
+
+ // Adjust by speed limit determined during composition.
+ speed_scale /= m_compose_speed_scale;
+
+ if (m_system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
+ // Run at intended presentation rate during video playback.
+ speed_scale = 1.f;
+ }
+
+ const f32 effective_fps = 60.f / static_cast<f32>(m_swap_interval);
+ return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h
new file mode 100644
index 000000000..52e3595d2
--- /dev/null
+++ b/src/core/hle/service/vi/conductor.h
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+#include <unordered_map>
+
+#include "common/common_types.h"
+#include "common/polyfill_thread.h"
+#include "common/thread.h"
+
+namespace Core {
+class System;
+}
+
+namespace Core::Timing {
+struct EventType;
+}
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class Container;
+class DisplayList;
+class VsyncManager;
+
+class Conductor {
+public:
+ explicit Conductor(Core::System& system, Container& container, DisplayList& displays);
+ ~Conductor();
+
+ void LinkVsyncEvent(u64 display_id, Event* event);
+ void UnlinkVsyncEvent(u64 display_id, Event* event);
+
+private:
+ void ProcessVsync();
+ void VsyncThread(std::stop_token token);
+ s64 GetNextTicks() const;
+
+private:
+ Core::System& m_system;
+ Container& m_container;
+ std::unordered_map<u64, VsyncManager> m_vsync_managers;
+ std::shared_ptr<Core::Timing::EventType> m_event;
+ Common::Event m_signal;
+ std::jthread m_thread;
+
+private:
+ s32 m_swap_interval = 1;
+ f32 m_compose_speed_scale = 1.0f;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/container.cpp b/src/core/hle/service/vi/container.cpp
new file mode 100644
index 000000000..310a207f1
--- /dev/null
+++ b/src/core/hle/service/vi/container.cpp
@@ -0,0 +1,228 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/nvdrv/nvdrv_interface.h"
+#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/vi_results.h"
+
+namespace Service::VI {
+
+Container::Container(Core::System& system) {
+ m_displays.CreateDisplay(DisplayName{"Default"});
+ m_displays.CreateDisplay(DisplayName{"External"});
+ m_displays.CreateDisplay(DisplayName{"Edid"});
+ m_displays.CreateDisplay(DisplayName{"Internal"});
+ m_displays.CreateDisplay(DisplayName{"Null"});
+
+ m_binder_driver =
+ system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true);
+ m_surface_flinger = m_binder_driver->GetSurfaceFlinger();
+
+ const auto nvdrv =
+ system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
+ m_shared_buffer_manager.emplace(system, *this, nvdrv);
+
+ m_displays.ForEachDisplay(
+ [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); });
+
+ m_conductor.emplace(system, *this, m_displays);
+}
+
+Container::~Container() {
+ this->OnTerminate();
+}
+
+void Container::OnTerminate() {
+ std::scoped_lock lk{m_lock};
+
+ m_is_shut_down = true;
+
+ m_layers.ForEachLayer([&](auto& layer) {
+ if (layer.IsOpen()) {
+ this->DestroyBufferQueueLocked(&layer);
+ }
+ });
+
+ m_displays.ForEachDisplay(
+ [&](auto& display) { m_surface_flinger->RemoveDisplay(display.GetId()); });
+}
+
+SharedBufferManager* Container::GetSharedBufferManager() {
+ return std::addressof(*m_shared_buffer_manager);
+}
+
+Result Container::GetBinderDriver(
+ std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) {
+ *out_binder_driver = m_binder_driver;
+ R_SUCCEED();
+}
+
+Result Container::GetLayerProducerHandle(
+ std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId());
+ R_UNLESS(binder != nullptr, VI::ResultNotFound);
+
+ *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder);
+ R_SUCCEED();
+}
+
+Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) {
+ auto* const display = m_displays.GetDisplayByName(display_name);
+ R_UNLESS(display != nullptr, VI::ResultNotFound);
+
+ *out_display_id = display->GetId();
+ R_SUCCEED();
+}
+
+Result Container::CloseDisplay(u64 display_id) {
+ R_SUCCEED();
+}
+
+Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid));
+}
+
+Result Container::DestroyManagedLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+
+ // Try to close, if open, but don't fail if not.
+ this->CloseLayerLocked(layer_id);
+
+ R_RETURN(this->DestroyLayerLocked(layer_id));
+}
+
+Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid));
+}
+
+Result Container::CloseLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->CloseLayerLocked(layer_id));
+}
+
+Result Container::SetLayerVisibility(u64 layer_id, bool visible) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible);
+ R_SUCCEED();
+}
+
+Result Container::SetLayerBlending(u64 layer_id, bool enabled) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(),
+ enabled ? Nvnflinger::LayerBlending::Coverage
+ : Nvnflinger::LayerBlending::None);
+ R_SUCCEED();
+}
+
+void Container::LinkVsyncEvent(u64 display_id, Event* event) {
+ std::scoped_lock lk{m_lock};
+ m_conductor->LinkVsyncEvent(display_id, event);
+}
+
+void Container::UnlinkVsyncEvent(u64 display_id, Event* event) {
+ std::scoped_lock lk{m_lock};
+ m_conductor->UnlinkVsyncEvent(display_id, event);
+}
+
+Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) {
+ std::scoped_lock lk{m_lock};
+ R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {}));
+ R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {}));
+}
+
+Result Container::DestroyStrayLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+ R_TRY(this->CloseLayerLocked(layer_id));
+ R_RETURN(this->DestroyLayerLocked(layer_id));
+}
+
+Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
+ auto* const display = m_displays.GetDisplayById(display_id);
+ R_UNLESS(display != nullptr, VI::ResultNotFound);
+
+ auto* const layer = m_layers.CreateLayer(owner_aruid, display);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ *out_layer_id = layer->GetId();
+ R_SUCCEED();
+}
+
+Result Container::DestroyLayerLocked(u64 layer_id) {
+ R_SUCCEED_IF(m_layers.DestroyLayer(layer_id));
+ R_THROW(VI::ResultNotFound);
+}
+
+Result Container::OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid) {
+ R_UNLESS(!m_is_shut_down, VI::ResultOperationFailed);
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+ R_UNLESS(!layer->IsOpen(), VI::ResultOperationFailed);
+ R_UNLESS(layer->GetOwnerAruid() == aruid, VI::ResultPermissionDenied);
+
+ this->CreateBufferQueueLocked(layer);
+ *out_producer_binder_id = layer->GetProducerBinderId();
+
+ R_SUCCEED();
+}
+
+Result Container::CloseLayerLocked(u64 layer_id) {
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+ R_UNLESS(layer->IsOpen(), VI::ResultOperationFailed);
+
+ this->DestroyBufferQueueLocked(layer);
+
+ R_SUCCEED();
+}
+
+void Container::CreateBufferQueueLocked(Layer* layer) {
+ s32 consumer_binder_id, producer_binder_id;
+ m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id);
+ layer->Open(consumer_binder_id, producer_binder_id);
+
+ if (auto* display = layer->GetDisplay(); display != nullptr) {
+ m_surface_flinger->AddLayerToDisplayStack(display->GetId(), consumer_binder_id);
+ }
+}
+
+void Container::DestroyBufferQueueLocked(Layer* layer) {
+ if (auto* display = layer->GetDisplay(); display != nullptr) {
+ m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(),
+ layer->GetConsumerBinderId());
+ }
+
+ layer->Close();
+ m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(),
+ layer->GetProducerBinderId());
+}
+
+bool Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale,
+ u64 display_id) {
+ std::scoped_lock lk{m_lock};
+ return m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale,
+ display_id);
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/container.h b/src/core/hle/service/vi/container.h
new file mode 100644
index 000000000..cd0d2ca86
--- /dev/null
+++ b/src/core/hle/service/vi/container.h
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <optional>
+
+#include "core/hle/service/vi/conductor.h"
+#include "core/hle/service/vi/display_list.h"
+#include "core/hle/service/vi/layer_list.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
+
+union Result;
+
+namespace Service::android {
+class BufferQueueProducer;
+}
+
+namespace Service::Nvnflinger {
+class IHOSBinderDriver;
+class SurfaceFlinger;
+} // namespace Service::Nvnflinger
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class SharedBufferManager;
+
+class Container {
+public:
+ explicit Container(Core::System& system);
+ ~Container();
+
+ void OnTerminate();
+
+ SharedBufferManager* GetSharedBufferManager();
+
+ Result GetBinderDriver(std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver);
+ Result GetLayerProducerHandle(std::shared_ptr<android::BufferQueueProducer>* out_producer,
+ u64 layer_id);
+
+ Result OpenDisplay(u64* out_display_id, const DisplayName& display_name);
+ Result CloseDisplay(u64 display_id);
+
+ // Managed layers are created by the interaction between am and ommdisp
+ // on behalf of an applet. Their lifetime ends with the lifetime of the
+ // applet's ISelfController.
+ Result CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid);
+ Result DestroyManagedLayer(u64 layer_id);
+ Result OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid);
+ Result CloseLayer(u64 layer_id);
+
+ // Stray layers are created by non-applet sysmodules. Their lifetime ends
+ // with the lifetime of the IApplicationDisplayService which created them.
+ Result CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id);
+ Result DestroyStrayLayer(u64 layer_id);
+
+ Result SetLayerVisibility(u64 layer_id, bool visible);
+ Result SetLayerBlending(u64 layer_id, bool enabled);
+
+ void LinkVsyncEvent(u64 display_id, Event* event);
+ void UnlinkVsyncEvent(u64 display_id, Event* event);
+
+private:
+ Result CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid);
+ Result DestroyLayerLocked(u64 layer_id);
+ Result OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid);
+ Result CloseLayerLocked(u64 layer_id);
+
+ void CreateBufferQueueLocked(Layer* layer);
+ void DestroyBufferQueueLocked(Layer* layer);
+
+public:
+ bool ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id);
+
+private:
+ std::mutex m_lock{};
+ DisplayList m_displays{};
+ LayerList m_layers{};
+ std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_driver{};
+ std::shared_ptr<Nvnflinger::SurfaceFlinger> m_surface_flinger{};
+ std::optional<SharedBufferManager> m_shared_buffer_manager{};
+ std::optional<Conductor> m_conductor{};
+ bool m_is_shut_down{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display.h b/src/core/hle/service/vi/display.h
new file mode 100644
index 000000000..fceda75e3
--- /dev/null
+++ b/src/core/hle/service/vi/display.h
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+class Display {
+public:
+ constexpr Display() = default;
+
+ void Initialize(u64 id, const DisplayName& display_name) {
+ m_id = id;
+ m_display_name = display_name;
+ m_is_initialized = true;
+ }
+
+ void Finalize() {
+ m_id = {};
+ m_display_name = {};
+ m_is_initialized = {};
+ }
+
+ u64 GetId() const {
+ return m_id;
+ }
+
+ const DisplayName& GetDisplayName() const {
+ return m_display_name;
+ }
+
+ bool IsInitialized() const {
+ return m_is_initialized;
+ }
+
+private:
+ u64 m_id{};
+ DisplayName m_display_name{};
+ bool m_is_initialized{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
deleted file mode 100644
index 7f2af9acc..000000000
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <algorithm>
-#include <utility>
-
-#include <fmt/format.h>
-
-#include "common/assert.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/nvdrv/core/container.h"
-#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_core.h"
-#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
-#include "core/hle/service/nvnflinger/hardware_composer.h"
-#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-#include "core/hle/service/vi/vi_results.h"
-
-namespace Service::VI {
-
-struct BufferQueue {
- std::shared_ptr<android::BufferQueueCore> core;
- std::unique_ptr<android::BufferQueueProducer> producer;
- std::unique_ptr<android::BufferQueueConsumer> consumer;
-};
-
-static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
- Service::Nvidia::NvCore::NvMap& nvmap) {
- auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
- return {
- buffer_queue_core,
- std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
- std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
-}
-
-Display::Display(u64 id, std::string name_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_,
- KernelHelpers::ServiceContext& service_context_, Core::System& system_)
- : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_},
- service_context{service_context_} {
- hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>();
- vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id));
-}
-
-Display::~Display() {
- service_context.CloseEvent(vsync_event);
-}
-
-Layer& Display::GetLayer(std::size_t index) {
- size_t i = 0;
- for (auto& layer : layers) {
- if (!layer->IsOpen() || !layer->IsVisible()) {
- continue;
- }
-
- if (i == index) {
- return *layer;
- }
-
- i++;
- }
-
- UNREACHABLE();
-}
-
-size_t Display::GetNumLayers() const {
- return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); });
-}
-
-Kernel::KReadableEvent* Display::GetVSyncEvent() {
- return &vsync_event->GetReadableEvent();
-}
-
-void Display::SignalVSyncEvent() {
- vsync_event->Signal();
-}
-
-void Display::CreateLayer(u64 layer_id, u32 binder_id,
- Service::Nvidia::NvCore::Container& nv_core) {
- auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
-
- auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
- buffer_item_consumer->Connect(false);
-
- layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer,
- std::move(buffer_item_consumer)));
-
- if (is_abandoned) {
- this->FindLayer(layer_id)->GetConsumer().Abandon();
- }
-
- hos_binder_driver_server.RegisterProducer(std::move(producer));
-}
-
-void Display::DestroyLayer(u64 layer_id) {
- if (auto* layer = this->FindLayer(layer_id); layer != nullptr) {
- layer->GetConsumer().Abandon();
- }
-
- std::erase_if(layers,
- [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
-}
-
-void Display::Abandon() {
- for (auto& layer : layers) {
- layer->GetConsumer().Abandon();
- }
- is_abandoned = true;
-}
-
-Layer* Display::FindLayer(u64 layer_id) {
- const auto itr =
- std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
- return layer->GetLayerId() == layer_id;
- });
-
- if (itr == layers.end()) {
- return nullptr;
- }
-
- return itr->get();
-}
-
-const Layer* Display::FindLayer(u64 layer_id) const {
- const auto itr =
- std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
- return layer->GetLayerId() == layer_id;
- });
-
- if (itr == layers.end()) {
- return nullptr;
- }
-
- return itr->get();
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
deleted file mode 100644
index 220292cff..000000000
--- a/src/core/hle/service/vi/display/vi_display.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "core/hle/result.h"
-
-namespace Core {
-class System;
-}
-
-namespace Kernel {
-class KEvent;
-class KReadableEvent;
-} // namespace Kernel
-
-namespace Service::android {
-class BufferQueueProducer;
-}
-
-namespace Service::KernelHelpers {
-class ServiceContext;
-}
-
-namespace Service::Nvnflinger {
-class HardwareComposer;
-class HosBinderDriverServer;
-} // namespace Service::Nvnflinger
-
-namespace Service::Nvidia::NvCore {
-class Container;
-class NvMap;
-} // namespace Service::Nvidia::NvCore
-
-namespace Service::VI {
-
-class Layer;
-
-/// Represents a single display type
-class Display {
-public:
- YUZU_NON_COPYABLE(Display);
- YUZU_NON_MOVEABLE(Display);
-
- /// Constructs a display with a given unique ID and name.
- ///
- /// @param id The unique ID for this display.
- /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance.
- /// @param service_context_ The ServiceContext for the owning service.
- /// @param name_ The name for this display.
- /// @param system_ The global system instance.
- ///
- Display(u64 id, std::string name_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_,
- KernelHelpers::ServiceContext& service_context_, Core::System& system_);
- ~Display();
-
- /// Gets the unique ID assigned to this display.
- u64 GetID() const {
- return display_id;
- }
-
- /// Gets the name of this display
- const std::string& GetName() const {
- return name;
- }
-
- /// Whether or not this display has any layers added to it.
- bool HasLayers() const {
- return GetNumLayers() > 0;
- }
-
- /// Gets a layer for this display based off an index.
- Layer& GetLayer(std::size_t index);
-
- std::size_t GetNumLayers() const;
-
- /// Gets the internal vsync event.
- Kernel::KReadableEvent* GetVSyncEvent();
-
- /// Signals the internal vsync event.
- void SignalVSyncEvent();
-
- /// Creates and adds a layer to this display with the given ID.
- ///
- /// @param layer_id The ID to assign to the created layer.
- /// @param binder_id The ID assigned to the buffer queue.
- ///
- void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
-
- /// Removes a layer from this display with the given ID.
- ///
- /// @param layer_id The ID assigned to the layer to destroy.
- ///
- void DestroyLayer(u64 layer_id);
-
- /// Resets the display for a new connection.
- void Reset() {
- layers.clear();
- }
-
- void Abandon();
-
- /// Attempts to find a layer with the given ID.
- ///
- /// @param layer_id The layer ID.
- ///
- /// @returns If found, the Layer instance with the given ID.
- /// If not found, then nullptr is returned.
- ///
- Layer* FindLayer(u64 layer_id);
-
- /// Attempts to find a layer with the given ID.
- ///
- /// @param layer_id The layer ID.
- ///
- /// @returns If found, the Layer instance with the given ID.
- /// If not found, then nullptr is returned.
- ///
- const Layer* FindLayer(u64 layer_id) const;
-
- Nvnflinger::HardwareComposer& GetComposer() const {
- return *hardware_composer;
- }
-
-private:
- u64 display_id;
- std::string name;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
- KernelHelpers::ServiceContext& service_context;
-
- std::vector<std::unique_ptr<Layer>> layers;
- std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer;
- Kernel::KEvent* vsync_event{};
- bool is_abandoned{};
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display_list.h b/src/core/hle/service/vi/display_list.h
new file mode 100644
index 000000000..f710ac472
--- /dev/null
+++ b/src/core/hle/service/vi/display_list.h
@@ -0,0 +1,83 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <cstring>
+
+#include "core/hle/service/vi/display.h"
+
+namespace Service::VI {
+
+class DisplayList {
+public:
+ constexpr DisplayList() = default;
+
+ bool CreateDisplay(const DisplayName& name) {
+ Display* const display = this->GetFreeDisplay();
+ if (!display) {
+ return false;
+ }
+
+ display->Initialize(m_next_id++, name);
+ return true;
+ }
+
+ bool DestroyDisplay(u64 display_id) {
+ Display* display = this->GetDisplayById(display_id);
+ if (!display) {
+ return false;
+ }
+
+ display->Finalize();
+ return true;
+ }
+
+ Display* GetDisplayByName(const DisplayName& name) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized() &&
+ std::strncmp(name.data(), display.GetDisplayName().data(), sizeof(DisplayName)) ==
+ 0) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+ Display* GetDisplayById(u64 display_id) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized() && display.GetId() == display_id) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+ template <typename F>
+ void ForEachDisplay(F&& cb) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized()) {
+ cb(display);
+ }
+ }
+ }
+
+private:
+ Display* GetFreeDisplay() {
+ for (auto& display : m_displays) {
+ if (!display.IsInitialized()) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+ std::array<Display, 8> m_displays{};
+ u64 m_next_id{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer.h b/src/core/hle/service/vi/layer.h
new file mode 100644
index 000000000..b85c8df61
--- /dev/null
+++ b/src/core/hle/service/vi/layer.h
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Service::VI {
+
+class Display;
+
+class Layer {
+public:
+ constexpr Layer() = default;
+
+ void Initialize(u64 id, u64 owner_aruid, Display* display) {
+ m_id = id;
+ m_owner_aruid = owner_aruid;
+ m_display = display;
+ m_is_initialized = true;
+ }
+
+ void Finalize() {
+ m_id = {};
+ m_display = {};
+ m_is_initialized = {};
+ }
+
+ void Open(s32 consumer_binder_id, s32 producer_binder_id) {
+ m_consumer_binder_id = consumer_binder_id;
+ m_producer_binder_id = producer_binder_id;
+ m_is_open = true;
+ }
+
+ void Close() {
+ m_producer_binder_id = {};
+ m_consumer_binder_id = {};
+ m_is_open = {};
+ }
+
+ u64 GetId() const {
+ return m_id;
+ }
+
+ u64 GetOwnerAruid() const {
+ return m_owner_aruid;
+ }
+
+ Display* GetDisplay() const {
+ return m_display;
+ }
+
+ s32 GetConsumerBinderId() const {
+ return m_consumer_binder_id;
+ }
+
+ s32 GetProducerBinderId() const {
+ return m_producer_binder_id;
+ }
+
+ bool IsInitialized() const {
+ return m_is_initialized;
+ }
+
+ bool IsOpen() const {
+ return m_is_open;
+ }
+
+private:
+ u64 m_id{};
+ u64 m_owner_aruid{};
+ Display* m_display{};
+ s32 m_consumer_binder_id{};
+ s32 m_producer_binder_id{};
+ bool m_is_initialized{};
+ bool m_is_open{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp
deleted file mode 100644
index eca35d82a..000000000
--- a/src/core/hle/service/vi/layer/vi_layer.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/nvnflinger/hwc_layer.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-
-namespace Service::VI {
-
-Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
- android::BufferQueueProducer& binder_,
- std::shared_ptr<android::BufferItemConsumer>&& consumer_)
- : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
- consumer_)},
- blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {}
-
-Layer::~Layer() = default;
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
deleted file mode 100644
index 14e229903..000000000
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <utility>
-
-#include "common/common_types.h"
-
-namespace Service::android {
-class BufferItemConsumer;
-class BufferQueueCore;
-class BufferQueueProducer;
-} // namespace Service::android
-
-namespace Service::Nvnflinger {
-enum class LayerBlending : u32;
-}
-
-namespace Service::VI {
-
-/// Represents a single display layer.
-class Layer {
-public:
- /// Constructs a layer with a given ID and buffer queue.
- ///
- /// @param layer_id_ The ID to assign to this layer.
- /// @param binder_id_ The binder ID to assign to this layer.
- /// @param binder_ The buffer producer queue for this layer to use.
- ///
- Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
- android::BufferQueueProducer& binder_,
- std::shared_ptr<android::BufferItemConsumer>&& consumer_);
- ~Layer();
-
- Layer(const Layer&) = delete;
- Layer& operator=(const Layer&) = delete;
-
- Layer(Layer&&) = default;
- Layer& operator=(Layer&&) = delete;
-
- /// Gets the ID for this layer.
- u64 GetLayerId() const {
- return layer_id;
- }
-
- /// Gets the binder ID for this layer.
- u32 GetBinderId() const {
- return binder_id;
- }
-
- /// Gets a reference to the buffer queue this layer is using.
- android::BufferQueueProducer& GetBufferQueue() {
- return binder;
- }
-
- /// Gets a const reference to the buffer queue this layer is using.
- const android::BufferQueueProducer& GetBufferQueue() const {
- return binder;
- }
-
- android::BufferItemConsumer& GetConsumer() {
- return *consumer;
- }
-
- const android::BufferItemConsumer& GetConsumer() const {
- return *consumer;
- }
-
- android::BufferQueueCore& Core() {
- return core;
- }
-
- const android::BufferQueueCore& Core() const {
- return core;
- }
-
- bool IsVisible() const {
- return visible;
- }
-
- void SetVisibility(bool v) {
- visible = v;
- }
-
- bool IsOpen() const {
- return open;
- }
-
- bool Close() {
- return std::exchange(open, false);
- }
-
- bool Open() {
- return !std::exchange(open, true);
- }
-
- Nvnflinger::LayerBlending GetBlending() {
- return blending;
- }
-
- void SetBlending(Nvnflinger::LayerBlending b) {
- blending = b;
- }
-
-private:
- const u64 layer_id;
- const u32 binder_id;
- android::BufferQueueCore& core;
- android::BufferQueueProducer& binder;
- std::shared_ptr<android::BufferItemConsumer> consumer;
- Service::Nvnflinger::LayerBlending blending;
- bool open;
- bool visible;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer_list.h b/src/core/hle/service/vi/layer_list.h
new file mode 100644
index 000000000..1738ede9a
--- /dev/null
+++ b/src/core/hle/service/vi/layer_list.h
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/vi/layer.h"
+
+namespace Service::VI {
+
+class LayerList {
+public:
+ constexpr LayerList() = default;
+
+ Layer* CreateLayer(u64 owner_aruid, Display* display) {
+ Layer* const layer = GetFreeLayer();
+ if (!layer) {
+ return nullptr;
+ }
+
+ layer->Initialize(++m_next_id, owner_aruid, display);
+ return layer;
+ }
+
+ bool DestroyLayer(u64 layer_id) {
+ Layer* const layer = GetLayerById(layer_id);
+ if (!layer) {
+ return false;
+ }
+
+ layer->Finalize();
+ return true;
+ }
+
+ Layer* GetLayerById(u64 layer_id) {
+ for (auto& layer : m_layers) {
+ if (layer.IsInitialized() && layer.GetId() == layer_id) {
+ return &layer;
+ }
+ }
+
+ return nullptr;
+ }
+
+ template <typename F>
+ void ForEachLayer(F&& cb) {
+ for (auto& layer : m_layers) {
+ if (layer.IsInitialized()) {
+ cb(layer);
+ }
+ }
+ }
+
+private:
+ Layer* GetFreeLayer() {
+ for (auto& layer : m_layers) {
+ if (!layer.IsInitialized()) {
+ return &layer;
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+ std::array<Layer, 8> m_layers{};
+ u64 m_next_id{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp
index 17f2f3b8f..9f856282e 100644
--- a/src/core/hle/service/vi/manager_display_service.cpp
+++ b/src/core/hle/service/vi/manager_display_service.cpp
@@ -2,22 +2,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/manager_display_service.h"
-#include "core/hle/service/vi/vi_results.h"
namespace Service::VI {
IManagerDisplayService::IManagerDisplayService(Core::System& system_,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} {
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} {
// clang-format off
static const FunctionInfo functions[] = {
{200, nullptr, "AllocateProcessHeapBlock"},
{201, nullptr, "FreeProcessHeapBlock"},
{1102, nullptr, "GetDisplayResolution"},
{2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"},
- {2011, nullptr, "DestroyManagedLayer"},
+ {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"},
{2012, nullptr, "CreateStrayLayer"},
{2050, nullptr, "CreateIndirectLayer"},
{2051, nullptr, "DestroyIndirectLayer"},
@@ -102,19 +101,30 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_,
IManagerDisplayService::~IManagerDisplayService() = default;
-Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown,
- u64 display_id, AppletResourceUserId aruid) {
- LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown,
- display_id, aruid.pid);
+Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process,
+ u64* out_buffer_id, u64* out_layer_handle,
+ u64 display_id, bool enable_blending) {
+ R_RETURN(m_container->GetSharedBufferManager()->CreateSession(
+ owner_process, out_buffer_id, out_layer_handle, display_id, enable_blending));
+}
- const auto layer_id = m_nvnflinger.CreateLayer(display_id);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display={}", display_id);
- R_THROW(VI::ResultNotFound);
- }
+void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) {
+ m_container->GetSharedBufferManager()->DestroySession(owner_process);
+}
- *out_layer_id = *layer_id;
- R_SUCCEED();
+Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) {
+ R_RETURN(m_container->SetLayerBlending(layer_id, enabled));
+}
+
+Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
+ AppletResourceUserId aruid) {
+ LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid);
+ R_RETURN(m_container->CreateManagedLayer(out_layer_id, display_id, aruid.pid));
+}
+
+Result IManagerDisplayService::DestroyManagedLayer(u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
+ R_RETURN(m_container->DestroyManagedLayer(layer_id));
}
Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) {
@@ -123,8 +133,8 @@ Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) {
}
Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
- LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible);
- R_SUCCEED();
+ LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible);
+ R_RETURN(m_container->SetLayerVisibility(layer_id, visible));
}
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_display_service.h b/src/core/hle/service/vi/manager_display_service.h
index 60e646ee0..b1bdf7f41 100644
--- a/src/core/hle/service/vi/manager_display_service.h
+++ b/src/core/hle/service/vi/manager_display_service.h
@@ -4,21 +4,34 @@
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
+namespace Kernel {
+class KProcess;
+}
+
namespace Service::VI {
+class Container;
+
class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
public:
- explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
+ explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container);
~IManagerDisplayService() override;
-private:
- Result CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, u64 display_id,
+ Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id,
+ u64* out_layer_handle, u64 display_id, bool enable_blending);
+ void DestroySharedLayerSession(Kernel::KProcess* owner_process);
+
+ Result SetLayerBlending(bool enabled, u64 layer_id);
+
+public:
+ Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
AppletResourceUserId aruid);
+ Result DestroyManagedLayer(u64 layer_id);
Result AddToLayerStack(u32 stack_id, u64 layer_id);
Result SetLayerVisibility(bool visible, u64 layer_id);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
+ const std::shared_ptr<Container> m_container;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp
index a7eee4f04..0f16a15b4 100644
--- a/src/core/hle/service/vi/manager_root_service.cpp
+++ b/src/core/hle/service/vi/manager_root_service.cpp
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/manager_root_service.h"
#include "core/hle/service/vi/service_creator.h"
#include "core/hle/service/vi/vi.h"
@@ -10,11 +12,9 @@
namespace Service::VI {
-IManagerRootService::IManagerRootService(
- Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server)
- : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{
- hos_binder_driver_server} {
+IManagerRootService::IManagerRootService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} {
static const FunctionInfo functions[] = {
{2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"},
{3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -31,8 +31,8 @@ IManagerRootService::~IManagerRootService() = default;
Result IManagerRootService::GetDisplayService(
Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger,
- m_hos_binder_driver_server, Permission::Manager, policy));
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::Manager, policy));
}
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h
index e6cb77aeb..77cd32869 100644
--- a/src/core/hle/service/vi/manager_root_service.h
+++ b/src/core/hle/service/vi/manager_root_service.h
@@ -10,29 +10,23 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
+class Container;
class IApplicationDisplayService;
enum class Policy : u32;
class IManagerRootService final : public ServiceFramework<IManagerRootService> {
public:
- explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+ explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container);
~IManagerRootService() override;
-private:
Result GetDisplayService(
Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
Policy policy);
- Nvnflinger::Nvnflinger& m_nvnflinger;
- Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server;
+private:
+ const std::shared_ptr<Container> m_container;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp
index 1de9d61a4..2b8e5f957 100644
--- a/src/core/hle/service/vi/service_creator.cpp
+++ b/src/core/hle/service/vi/service_creator.cpp
@@ -22,8 +22,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
Result GetApplicationDisplayService(
std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
- Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission,
+ Core::System& system, std::shared_ptr<Container> container, Permission permission,
Policy policy) {
if (!IsValidServiceAccess(permission, policy)) {
@@ -32,7 +31,7 @@ Result GetApplicationDisplayService(
}
*out_application_display_service =
- std::make_shared<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server);
+ std::make_shared<IApplicationDisplayService>(system, std::move(container));
R_SUCCEED();
}
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h
index 8963bcd26..c6ba1797d 100644
--- a/src/core/hle/service/vi/service_creator.h
+++ b/src/core/hle/service/vi/service_creator.h
@@ -11,23 +11,18 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
union Result;
namespace Service::VI {
+class Container;
class IApplicationDisplayService;
enum class Permission;
enum class Policy : u32;
Result GetApplicationDisplayService(
std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
- Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission,
+ Core::System& system, std::shared_ptr<Container> container, Permission permission,
Policy policy);
} // namespace Service::VI
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp
index 90f7248a0..869b18961 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/vi/shared_buffer_manager.cpp
@@ -9,15 +9,15 @@
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
#include "core/hle/service/nvnflinger/pixel_format.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
#include "core/hle/service/vi/vi_results.h"
#include "video_core/gpu.h"
#include "video_core/host1x/host1x.h"
-namespace Service::Nvnflinger {
+namespace Service::VI {
namespace {
@@ -26,7 +26,6 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_
using Core::Memory::YUZU_PAGESIZE;
// Allocate memory for the system shared buffer.
- // FIXME: This memory belongs to vi's .data section.
auto& kernel = system.Kernel();
// Hold a temporary page group reference while we try to map it.
@@ -204,15 +203,15 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han
} // namespace
-FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
- std::shared_ptr<Nvidia::Module> nvdrv)
- : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {}
+SharedBufferManager::SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv)
+ : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {}
-FbShareBufferManager::~FbShareBufferManager() = default;
+SharedBufferManager::~SharedBufferManager() = default;
-Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id,
- u64* out_layer_handle, u64 display_id,
- LayerBlending blending) {
+Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id,
+ u64* out_layer_handle, u64 display_id,
+ bool enable_blending) {
std::scoped_lock lk{m_guard};
// Ensure we haven't already created.
@@ -237,7 +236,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
owner_process, m_system));
// Create new session.
- auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{});
+ auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
auto& session = it->second;
auto& container = m_nvdrv->GetContainer();
@@ -249,17 +248,18 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
session.nvmap_fd, map_address, SharedBufferSize));
// Create and open a layer for the display.
- session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value();
- m_flinger.OpenLayer(session.layer_id);
+ s32 producer_binder_id;
+ R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
+ std::addressof(session.layer_id), display_id));
- // Get the layer.
- VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id);
- ASSERT(layer != nullptr);
+ // Configure blending.
+ R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
// Get the producer and set preallocated buffers.
- auto& producer = layer->GetBufferQueue();
- MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle);
- MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle);
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id));
+ MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle);
+ MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle);
// Assign outputs.
*out_buffer_id = m_buffer_id;
@@ -269,7 +269,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
R_SUCCEED();
}
-void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
+void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) {
std::scoped_lock lk{m_guard};
if (m_buffer_id == 0) {
@@ -285,7 +285,7 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
auto& session = it->second;
// Destroy the layer.
- m_flinger.DestroyLayer(session.layer_id);
+ R_ASSERT(m_container.DestroyStrayLayer(session.layer_id));
// Close nvmap handle.
FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
@@ -301,11 +301,11 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
m_sessions.erase(it);
}
-Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
- s32* out_nvmap_handle,
- SharedMemoryPoolLayout* out_pool_layout,
- u64 buffer_id,
- u64 applet_resource_user_id) {
+Result SharedBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
+ s32* out_nvmap_handle,
+ SharedMemoryPoolLayout* out_pool_layout,
+ u64 buffer_id,
+ u64 applet_resource_user_id) {
std::scoped_lock lk{m_guard};
R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);
@@ -319,36 +319,20 @@ Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
R_SUCCEED();
}
-Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {
- // Ensure the layer id is valid.
- R_UNLESS(layer_id > 0, VI::ResultNotFound);
-
- // Get the layer.
- VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id);
- R_UNLESS(layer != nullptr, VI::ResultNotFound);
-
- // We succeeded.
- *out_layer = layer;
- R_SUCCEED();
-}
-
-Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
- std::array<s32, 4>& out_slot_indexes,
- s64* out_target_slot, u64 layer_id) {
+Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
+ std::array<s32, 4>& out_slot_indexes,
+ s64* out_target_slot, u64 layer_id) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
-
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Get the next buffer from the producer.
s32 slot;
- R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
- SharedBufferWidth, SharedBufferHeight,
- SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
+ R_UNLESS(producer->DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
+ SharedBufferWidth, SharedBufferHeight,
+ SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
VI::ResultOperationFailed);
// Assign remaining outputs.
@@ -359,27 +343,24 @@ Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
R_SUCCEED();
}
-Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
- Common::Rectangle<s32> crop_region,
- u32 transform, s32 swap_interval,
- u64 layer_id, s64 slot) {
+Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
+ Common::Rectangle<s32> crop_region,
+ u32 transform, s32 swap_interval, u64 layer_id,
+ s64 slot) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
-
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Request to queue the buffer.
std::shared_ptr<android::GraphicBuffer> buffer;
- R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
+ R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
android::Status::NoError,
VI::ResultOperationFailed);
ON_RESULT_FAILURE {
- producer.CancelBuffer(static_cast<s32>(slot), fence);
+ producer->CancelBuffer(static_cast<s32>(slot), fence);
};
// Queue the buffer to the producer.
@@ -389,7 +370,7 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
input.fence = fence;
input.transform = static_cast<android::NativeWindowTransform>(transform);
input.swap_interval = swap_interval;
- R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
+ R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
android::Status::NoError,
VI::ResultOperationFailed);
@@ -397,25 +378,36 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
R_SUCCEED();
}
-Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
- u64 layer_id) {
+Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
+ // Get the producer.
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
+
+ // Cancel.
+ producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence());
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
+ u64 layer_id) {
+ std::scoped_lock lk{m_guard};
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Set the event.
- *out_event = std::addressof(producer.GetNativeHandle());
+ *out_event = producer->GetNativeHandle({});
// We succeeded.
R_SUCCEED();
}
-Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
+Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
Common::ScratchBuffer<u32> scratch;
@@ -444,4 +436,4 @@ Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32
R_SUCCEED();
}
-} // namespace Service::Nvnflinger
+} // namespace Service::VI
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h
index b79a7d23a..7c9bb7199 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
+++ b/src/core/hle/service/vi/shared_buffer_manager.h
@@ -8,15 +8,27 @@
#include "common/math_util.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvnflinger/hwc_layer.h"
#include "core/hle/service/nvnflinger/nvnflinger.h"
#include "core/hle/service/nvnflinger/ui/fence.h"
namespace Kernel {
class KPageGroup;
+class KReadableEvent;
+} // namespace Kernel
+
+namespace Service::android {
+class BufferQueueProducer;
+}
+
+namespace Service::Nvidia {
+class Module;
}
-namespace Service::Nvnflinger {
+union Result;
+
+namespace Service::VI {
+
+class Container;
struct SharedMemorySlot {
u64 buffer_offset;
@@ -32,17 +44,17 @@ struct SharedMemoryPoolLayout {
};
static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
-struct FbShareSession;
+struct SharedBufferSession;
-class FbShareBufferManager final {
+class SharedBufferManager final {
public:
- explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
- std::shared_ptr<Nvidia::Module> nvdrv);
- ~FbShareBufferManager();
+ explicit SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv);
+ ~SharedBufferManager();
- Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle,
- u64 display_id, LayerBlending blending);
- void Finalize(Kernel::KProcess* owner_process);
+ Result CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle,
+ u64 display_id, bool enable_blending);
+ void DestroySession(Kernel::KProcess* owner_process);
Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,
SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,
@@ -51,32 +63,30 @@ public:
s64* out_target_slot, u64 layer_id);
Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
u32 transform, s32 swap_interval, u64 layer_id, s64 slot);
+ Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);
private:
- Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
-
-private:
u64 m_next_buffer_id = 1;
u64 m_display_id = 0;
u64 m_buffer_id = 0;
SharedMemoryPoolLayout m_pool_layout = {};
- std::map<u64, FbShareSession> m_sessions;
+ std::map<u64, SharedBufferSession> m_sessions;
std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
std::mutex m_guard;
Core::System& m_system;
- Nvnflinger& m_flinger;
- std::shared_ptr<Nvidia::Module> m_nvdrv;
+ Container& m_container;
+ const std::shared_ptr<Nvidia::Module> m_nvdrv;
};
-struct FbShareSession {
+struct SharedBufferSession {
Nvidia::DeviceFD nvmap_fd = {};
Nvidia::NvCore::SessionId session_id = {};
u64 layer_id = {};
u32 buffer_nvmap_handle = 0;
};
-} // namespace Service::Nvnflinger
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp
index 1e1cfc817..c3c50b07b 100644
--- a/src/core/hle/service/vi/system_display_service.cpp
+++ b/src/core/hle/service/vi/system_display_service.cpp
@@ -3,15 +3,15 @@
#include "common/settings.h"
#include "core/hle/service/cmif_serialization.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/system_display_service.h"
#include "core/hle/service/vi/vi_types.h"
namespace Service::VI {
ISystemDisplayService::ISystemDisplayService(Core::System& system_,
- Nvnflinger::Nvnflinger& nvnflinger)
- : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} {
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} {
// clang-format off
static const FunctionInfo functions[] = {
{1200, nullptr, "GetZOrderCountMin"},
@@ -29,7 +29,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,
{2400, nullptr, "OpenIndirectLayer"},
{2401, nullptr, "CloseIndirectLayer"},
{2402, nullptr, "FlipIndirectLayer"},
- {3000, nullptr, "ListDisplayModes"},
+ {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"},
{3001, nullptr, "ListDisplayRgbRanges"},
{3002, nullptr, "ListDisplayContentTypes"},
{3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"},
@@ -59,7 +59,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,
{8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"},
{8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"},
{8257, nullptr, "FillSharedFrameBufferColor"},
- {8258, nullptr, "CancelSharedFrameBuffer"},
+ {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"},
{9000, nullptr, "GetDp2hdmiController"},
};
// clang-format on
@@ -80,31 +80,50 @@ Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
R_SUCCEED();
}
-Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height,
- Out<f32> out_refresh_rate, Out<u32> out_unknown) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
+Result ISystemDisplayService::ListDisplayModes(
+ Out<u64> out_count, u64 display_id,
+ OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes) {
+ LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id);
+
+ if (!out_display_modes.empty()) {
+ out_display_modes[0] = {
+ .width = 1920,
+ .height = 1080,
+ .refresh_rate = 60.f,
+ .unknown = {},
+ };
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id);
if (Settings::IsDockedMode()) {
- *out_width = static_cast<u32>(DisplayResolution::DockedWidth);
- *out_height = static_cast<u32>(DisplayResolution::DockedHeight);
+ out_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight);
} else {
- *out_width = static_cast<u32>(DisplayResolution::UndockedWidth);
- *out_height = static_cast<u32>(DisplayResolution::UndockedHeight);
+ out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight);
}
- *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games.
- *out_unknown = 0;
+ out_display_mode->refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games.
+ out_display_mode->unknown = 0;
R_SUCCEED();
}
Result ISystemDisplayService::GetSharedBufferMemoryHandleId(
Out<s32> out_nvmap_handle, Out<u64> out_size,
- OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
- u64 buffer_id, ClientAppletResourceUserId aruid) {
+ OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id,
+ ClientAppletResourceUserId aruid) {
LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid);
- R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId(
+ R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId(
out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid));
}
@@ -122,7 +141,7 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_f
Out<std::array<s32, 4>> out_slots,
Out<s64> out_target_slot, u64 layer_id) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer(
+ R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer(
out_fence, *out_slots, out_target_slot, layer_id));
}
@@ -131,15 +150,20 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,
u32 window_transform, s32 swap_interval,
u64 layer_id, s64 surface_id) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer(
+ R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer(
fence, crop_region, window_transform, swap_interval, layer_id, surface_id));
}
Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event,
- layer_id));
+ R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event,
+ layer_id));
+}
+
+Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot));
}
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h
index cfcb196fd..7228d826e 100644
--- a/src/core/hle/service/vi/system_display_service.h
+++ b/src/core/hle/service/vi/system_display_service.h
@@ -5,27 +5,28 @@
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/nvnflinger/ui/fence.h"
#include "core/hle/service/service.h"
-
-namespace Service::Nvnflinger {
-struct SharedMemoryPoolLayout;
-}
+#include "core/hle/service/vi/shared_buffer_manager.h"
namespace Service::VI {
+struct DisplayMode;
+
+class Container;
class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
public:
- explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
+ explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container);
~ISystemDisplayService() override;
private:
Result SetLayerZ(u32 z_value, u64 layer_id);
Result SetLayerVisibility(bool visible, u64 layer_id);
- Result GetDisplayMode(Out<u32> out_width, Out<u32> out_height, Out<f32> out_refresh_rate,
- Out<u32> out_unknown);
+ Result ListDisplayModes(Out<u64> out_count, u64 display_id,
+ OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes);
+ Result GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id);
Result GetSharedBufferMemoryHandleId(
Out<s32> out_nvmap_handle, Out<u64> out_size,
- OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
+ OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
u64 buffer_id, ClientAppletResourceUserId aruid);
Result OpenSharedLayer(u64 layer_id);
Result ConnectSharedLayer(u64 layer_id);
@@ -37,9 +38,10 @@ private:
Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
u32 window_transform, s32 swap_interval, u64 layer_id,
s64 surface_id);
+ Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
+ const std::shared_ptr<Container> m_container;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp
index 8789b4cfb..3489727d8 100644
--- a/src/core/hle/service/vi/system_root_service.cpp
+++ b/src/core/hle/service/vi/system_root_service.cpp
@@ -3,6 +3,7 @@
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/service_creator.h"
#include "core/hle/service/vi/system_root_service.h"
#include "core/hle/service/vi/vi.h"
@@ -10,10 +11,8 @@
namespace Service::VI {
-ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server)
- : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{
- hos_binder_driver_server} {
+ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} {
static const FunctionInfo functions[] = {
{1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"},
{3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -26,8 +25,8 @@ ISystemRootService::~ISystemRootService() = default;
Result ISystemRootService::GetDisplayService(
Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
LOG_DEBUG(Service_VI, "called");
- R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger,
- m_hos_binder_driver_server, Permission::System, policy));
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::System, policy));
}
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h
index 2c547faa5..9d5aa53d3 100644
--- a/src/core/hle/service/vi/system_root_service.h
+++ b/src/core/hle/service/vi/system_root_service.h
@@ -10,20 +10,15 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
+class Container;
class IApplicationDisplayService;
enum class Policy : u32;
class ISystemRootService final : public ServiceFramework<ISystemRootService> {
public:
- explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+ explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container);
~ISystemRootService() override;
private:
@@ -31,8 +26,7 @@ private:
Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
Policy policy);
- Nvnflinger::Nvnflinger& m_nvnflinger;
- Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server;
+ const std::shared_ptr<Container> m_container;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 304e589b7..b388efaf6 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -1,25 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "core/core.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/vi/application_display_service.h"
#include "core/hle/service/vi/application_root_service.h"
+#include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/manager_root_service.h"
#include "core/hle/service/vi/system_root_service.h"
#include "core/hle/service/vi/vi.h"
namespace Service::VI {
-void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) {
+void LoopProcess(Core::System& system, std::stop_token token) {
+ const auto container = std::make_shared<Container>(system);
+
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("vi:m", std::make_shared<IManagerRootService>(
- system, nvnflinger, hos_binder_driver_server));
+ server_manager->RegisterNamedService("vi:m",
+ std::make_shared<IManagerRootService>(system, container));
+ server_manager->RegisterNamedService("vi:s",
+ std::make_shared<ISystemRootService>(system, container));
server_manager->RegisterNamedService(
- "vi:s", std::make_shared<ISystemRootService>(system, nvnflinger, hos_binder_driver_server));
- server_manager->RegisterNamedService("vi:u", std::make_shared<IApplicationRootService>(
- system, nvnflinger, hos_binder_driver_server));
+ "vi:u", std::make_shared<IApplicationRootService>(system, container));
+
+ std::stop_callback cb(token, [=] { container->OnTerminate(); });
+
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 8e681370d..7c1f350d8 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -3,18 +3,14 @@
#pragma once
+#include "common/polyfill_thread.h"
+
namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
-void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+void LoopProcess(Core::System& system, std::stop_token token);
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h
index 91e4b380c..95ff66358 100644
--- a/src/core/hle/service/vi/vi_types.h
+++ b/src/core/hle/service/vi/vi_types.h
@@ -66,9 +66,17 @@ struct DisplayInfo {
};
static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
+struct DisplayMode {
+ u32 width;
+ u32 height;
+ f32 refresh_rate;
+ u32 unknown;
+};
+static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size");
+
class NativeWindow final {
public:
- constexpr explicit NativeWindow(u32 id_) : id{id_} {}
+ constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {}
constexpr explicit NativeWindow(const NativeWindow& other) = default;
private:
diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp
new file mode 100644
index 000000000..bdc4dfa96
--- /dev/null
+++ b/src/core/hle/service/vi/vsync_manager.cpp
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/vi/vsync_manager.h"
+
+namespace Service::VI {
+
+VsyncManager::VsyncManager() = default;
+VsyncManager::~VsyncManager() = default;
+
+void VsyncManager::SignalVsync() {
+ for (auto* event : m_vsync_events) {
+ event->Signal();
+ }
+}
+
+void VsyncManager::LinkVsyncEvent(Event* event) {
+ m_vsync_events.insert(event);
+}
+
+void VsyncManager::UnlinkVsyncEvent(Event* event) {
+ m_vsync_events.erase(event);
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h
new file mode 100644
index 000000000..5d45bb5ee
--- /dev/null
+++ b/src/core/hle/service/vi/vsync_manager.h
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <set>
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class DisplayList;
+
+class VsyncManager {
+public:
+ explicit VsyncManager();
+ ~VsyncManager();
+
+ void SignalVsync();
+ void LinkVsyncEvent(Event* event);
+ void UnlinkVsyncEvent(Event* event);
+
+private:
+ std::set<Event*> m_vsync_events;
+};
+
+} // namespace Service::VI