summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt320
-rw-r--r--src/core/core.cpp21
-rw-r--r--src/core/cpu_manager.cpp4
-rw-r--r--src/core/device_memory_manager.inc4
-rw-r--r--src/core/file_sys/control_metadata.h4
-rw-r--r--src/core/file_sys/fs_directory.h4
-rw-r--r--src/core/file_sys/fs_path_utility.h12
-rw-r--r--src/core/file_sys/fssystem/fssystem_aes_xts_storage.h1
-rw-r--r--src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp4
-rw-r--r--src/core/file_sys/program_metadata.cpp4
-rw-r--r--src/core/file_sys/system_archive/shared_font.cpp2
-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.cpp16
-rw-r--r--src/core/hle/service/am/am.h6
-rw-r--r--src/core/hle/service/am/am_types.h85
-rw-r--r--src/core/hle/service/am/applet.h12
-rw-r--r--src/core/hle/service/am/applet_ae.cpp73
-rw-r--r--src/core/hle/service/am/applet_ae.h39
-rw-r--r--src/core/hle/service/am/applet_common_functions.cpp63
-rw-r--r--src/core/hle/service/am/applet_common_functions.h24
-rw-r--r--src/core/hle/service/am/applet_data_broker.cpp4
-rw-r--r--src/core/hle/service/am/applet_manager.cpp23
-rw-r--r--src/core/hle/service/am/applet_message_queue.cpp2
-rw-r--r--src/core/hle/service/am/applet_message_queue.h35
-rw-r--r--src/core/hle/service/am/applet_oe.cpp42
-rw-r--r--src/core/hle/service/am/applet_oe.h37
-rw-r--r--src/core/hle/service/am/application_creator.cpp25
-rw-r--r--src/core/hle/service/am/application_creator.h16
-rw-r--r--src/core/hle/service/am/application_functions.cpp594
-rw-r--r--src/core/hle/service/am/application_functions.h58
-rw-r--r--src/core/hle/service/am/application_proxy.cpp115
-rw-r--r--src/core/hle/service/am/application_proxy.h33
-rw-r--r--src/core/hle/service/am/audio_controller.cpp91
-rw-r--r--src/core/hle/service/am/audio_controller.h36
-rw-r--r--src/core/hle/service/am/common_state_getter.cpp314
-rw-r--r--src/core/hle/service/am/common_state_getter.h77
-rw-r--r--src/core/hle/service/am/debug_functions.cpp44
-rw-r--r--src/core/hle/service/am/display_controller.cpp135
-rw-r--r--src/core/hle/service/am/display_controller.h30
-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_cabinet.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_controller.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_error.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_general.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_mii_edit.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_profile_select.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_software_keyboard.cpp2
-rw-r--r--src/core/hle/service/am/frontend/applet_web_browser.cpp4
-rw-r--r--src/core/hle/service/am/frontend/applets.cpp5
-rw-r--r--src/core/hle/service/am/global_state_controller.cpp34
-rw-r--r--src/core/hle/service/am/global_state_controller.h16
-rw-r--r--src/core/hle/service/am/home_menu_functions.cpp57
-rw-r--r--src/core/hle/service/am/home_menu_functions.h25
-rw-r--r--src/core/hle/service/am/idle.cpp25
-rw-r--r--src/core/hle/service/am/idle.h20
-rw-r--r--src/core/hle/service/am/library_applet_accessor.cpp202
-rw-r--r--src/core/hle/service/am/library_applet_accessor.h43
-rw-r--r--src/core/hle/service/am/library_applet_creator.cpp310
-rw-r--r--src/core/hle/service/am/library_applet_creator.h26
-rw-r--r--src/core/hle/service/am/library_applet_proxy.cpp143
-rw-r--r--src/core/hle/service/am/library_applet_proxy.h36
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.cpp338
-rw-r--r--src/core/hle/service/am/library_applet_self_accessor.h44
-rw-r--r--src/core/hle/service/am/library_applet_storage.cpp4
-rw-r--r--src/core/hle/service/am/lock_accessor.cpp71
-rw-r--r--src/core/hle/service/am/lock_accessor.h28
-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/omm.cpp48
-rw-r--r--src/core/hle/service/am/omm.h20
-rw-r--r--src/core/hle/service/am/process.cpp4
-rw-r--r--src/core/hle/service/am/process_winding_controller.cpp56
-rw-r--r--src/core/hle/service/am/process_winding_controller.h24
-rw-r--r--src/core/hle/service/am/self_controller.cpp470
-rw-r--r--src/core/hle/service/am/self_controller.h60
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.cpp79
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.h41
-rw-r--r--src/core/hle/service/am/service/applet_common_functions.cpp63
-rw-r--r--src/core/hle/service/am/service/applet_common_functions.h26
-rw-r--r--src/core/hle/service/am/service/application_accessor.cpp138
-rw-r--r--src/core/hle/service/am/service/application_accessor.h40
-rw-r--r--src/core/hle/service/am/service/application_creator.cpp35
-rw-r--r--src/core/hle/service/am/service/application_creator.h23
-rw-r--r--src/core/hle/service/am/service/application_functions.cpp485
-rw-r--r--src/core/hle/service/am/service/application_functions.h84
-rw-r--r--src/core/hle/service/am/service/application_proxy.cpp105
-rw-r--r--src/core/hle/service/am/service/application_proxy.h47
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.cpp42
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.h30
-rw-r--r--src/core/hle/service/am/service/audio_controller.cpp69
-rw-r--r--src/core/hle/service/am/service/audio_controller.h37
-rw-r--r--src/core/hle/service/am/service/common_state_getter.cpp278
-rw-r--r--src/core/hle/service/am/service/common_state_getter.h61
-rw-r--r--src/core/hle/service/am/service/cradle_firmware_updater.cpp52
-rw-r--r--src/core/hle/service/am/service/cradle_firmware_updater.h37
-rw-r--r--src/core/hle/service/am/service/debug_functions.cpp43
-rw-r--r--src/core/hle/service/am/service/debug_functions.h (renamed from src/core/hle/service/am/debug_functions.h)0
-rw-r--r--src/core/hle/service/am/service/display_controller.cpp105
-rw-r--r--src/core/hle/service/am/service/display_controller.h36
-rw-r--r--src/core/hle/service/am/service/global_state_controller.cpp61
-rw-r--r--src/core/hle/service/am/service/global_state_controller.h31
-rw-r--r--src/core/hle/service/am/service/home_menu_functions.cpp74
-rw-r--r--src/core/hle/service/am/service/home_menu_functions.h34
-rw-r--r--src/core/hle/service/am/service/library_applet_accessor.cpp157
-rw-r--r--src/core/hle/service/am/service/library_applet_accessor.h45
-rw-r--r--src/core/hle/service/am/service/library_applet_creator.cpp268
-rw-r--r--src/core/hle/service/am/service/library_applet_creator.h35
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.cpp132
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.h54
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.cpp325
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.h83
-rw-r--r--src/core/hle/service/am/service/lock_accessor.cpp75
-rw-r--r--src/core/hle/service/am/service/lock_accessor.h32
-rw-r--r--src/core/hle/service/am/service/process_winding_controller.cpp54
-rw-r--r--src/core/hle/service/am/service/process_winding_controller.h28
-rw-r--r--src/core/hle/service/am/service/self_controller.cpp394
-rw-r--r--src/core/hle/service/am/service/self_controller.h71
-rw-r--r--src/core/hle/service/am/service/storage.cpp48
-rw-r--r--src/core/hle/service/am/service/storage.h35
-rw-r--r--src/core/hle/service/am/service/storage_accessor.cpp68
-rw-r--r--src/core/hle/service/am/service/storage_accessor.h38
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.cpp131
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.h53
-rw-r--r--src/core/hle/service/am/service/window_controller.cpp86
-rw-r--r--src/core/hle/service/am/service/window_controller.h30
-rw-r--r--src/core/hle/service/am/spsm.cpp31
-rw-r--r--src/core/hle/service/am/spsm.h20
-rw-r--r--src/core/hle/service/am/storage.cpp59
-rw-r--r--src/core/hle/service/am/storage.h31
-rw-r--r--src/core/hle/service/am/storage_accessor.cpp90
-rw-r--r--src/core/hle/service/am/storage_accessor.h37
-rw-r--r--src/core/hle/service/am/system_applet_proxy.cpp136
-rw-r--r--src/core/hle/service/am/system_applet_proxy.h36
-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/am/window_controller.cpp86
-rw-r--r--src/core/hle/service/am/window_controller.h27
-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/btm/btm.cpp272
-rw-r--r--src/core/hle/service/btm/btm.h4
-rw-r--r--src/core/hle/service/btm/btm_debug.cpp33
-rw-r--r--src/core/hle/service/btm/btm_debug.h21
-rw-r--r--src/core/hle/service/btm/btm_system.cpp31
-rw-r--r--src/core/hle/service/btm/btm_system.h25
-rw-r--r--src/core/hle/service/btm/btm_system_core.cpp127
-rw-r--r--src/core/hle/service/btm/btm_system_core.h60
-rw-r--r--src/core/hle/service/btm/btm_user.cpp30
-rw-r--r--src/core/hle/service/btm/btm_user.h25
-rw-r--r--src/core/hle/service/btm/btm_user_core.cpp103
-rw-r--r--src/core/hle/service/btm/btm_user_core.h47
-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.cpp47
-rw-r--r--src/core/hle/service/glue/time/manager.h1
-rw-r--r--src/core/hle/service/glue/time/static.cpp58
-rw-r--r--src/core/hle/service/glue/time/time_zone.cpp36
-rw-r--r--src/core/hle/service/glue/time/worker.cpp2
-rw-r--r--src/core/hle/service/ldn/lan_discovery.cpp20
-rw-r--r--src/core/hle/service/ldn/lan_discovery.h5
-rw-r--r--src/core/hle/service/ldn/ldn.cpp802
-rw-r--r--src/core/hle/service/ldn/ldn.h6
-rw-r--r--src/core/hle/service/ldn/ldn_types.h68
-rw-r--r--src/core/hle/service/ldn/monitor_service.cpp43
-rw-r--r--src/core/hle/service/ldn/monitor_service.h28
-rw-r--r--src/core/hle/service/ldn/sf_monitor_service.cpp40
-rw-r--r--src/core/hle/service/ldn/sf_monitor_service.h26
-rw-r--r--src/core/hle/service/ldn/sf_service.cpp37
-rw-r--r--src/core/hle/service/ldn/sf_service.h21
-rw-r--r--src/core/hle/service/ldn/sf_service_monitor.cpp50
-rw-r--r--src/core/hle/service/ldn/sf_service_monitor.h26
-rw-r--r--src/core/hle/service/ldn/system_local_communication_service.cpp56
-rw-r--r--src/core/hle/service/ldn/system_local_communication_service.h25
-rw-r--r--src/core/hle/service/ldn/user_local_communication_service.cpp320
-rw-r--r--src/core/hle/service/ldn/user_local_communication_service.h103
-rw-r--r--src/core/hle/service/mii/mii.cpp9
-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/iplatform_service_manager.cpp305
-rw-r--r--src/core/hle/service/ns/iplatform_service_manager.h58
-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.h116
-rw-r--r--src/core/hle/service/ns/pdm_qry.cpp67
-rw-r--r--src/core/hle/service/ns/pdm_qry.h32
-rw-r--r--src/core/hle/service/ns/platform_service_manager.cpp273
-rw-r--r--src/core/hle/service/ns/platform_service_manager.h79
-rw-r--r--src/core/hle/service/ns/query_service.cpp56
-rw-r--r--src/core/hle/service/ns/query_service.h36
-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.h24
-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.cpp37
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h7
-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.h53
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp447
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.h82
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp67
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.h20
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.cpp66
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.h46
-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.cpp139
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.h69
-rw-r--r--src/core/hle/service/omm/omm.cpp22
-rw-r--r--src/core/hle/service/omm/omm.h14
-rw-r--r--src/core/hle/service/omm/operation_mode_manager.cpp49
-rw-r--r--src/core/hle/service/omm/operation_mode_manager.h20
-rw-r--r--src/core/hle/service/omm/policy_manager_system.cpp26
-rw-r--r--src/core/hle/service/omm/policy_manager_system.h20
-rw-r--r--src/core/hle/service/omm/power_state_interface.cpp32
-rw-r--r--src/core/hle/service/omm/power_state_interface.h20
-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.cpp134
-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/set/key_code_map.h973
-rw-r--r--src/core/hle/service/set/private_settings.h72
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.h4
-rw-r--r--src/core/hle/service/set/settings_server.cpp258
-rw-r--r--src/core/hle/service/set/settings_server.h37
-rw-r--r--src/core/hle/service/set/settings_types.h29
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp1394
-rw-r--r--src/core/hle/service/set/system_settings_server.h208
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp302
-rw-r--r--src/core/hle/service/vi/application_display_service.h81
-rw-r--r--src/core/hle/service/vi/application_root_service.cpp33
-rw-r--r--src/core/hle/service/vi/application_root_service.h33
-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.cpp226
-rw-r--r--src/core/hle/service/vi/container.h89
-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.h81
-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.h71
-rw-r--r--src/core/hle/service/vi/manager_display_service.cpp140
-rw-r--r--src/core/hle/service/vi/manager_display_service.h37
-rw-r--r--src/core/hle/service/vi/manager_root_service.cpp38
-rw-r--r--src/core/hle/service/vi/manager_root_service.h32
-rw-r--r--src/core/hle/service/vi/service_creator.cpp38
-rw-r--r--src/core/hle/service/vi/service_creator.h28
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.cpp431
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.h92
-rw-r--r--src/core/hle/service/vi/system_display_service.cpp169
-rw-r--r--src/core/hle/service/vi/system_display_service.h47
-rw-r--r--src/core/hle/service/vi/system_root_service.cpp32
-rw-r--r--src/core/hle/service/vi/system_root_service.h32
-rw-r--r--src/core/hle/service/vi/vi.cpp974
-rw-r--r--src/core/hle/service/vi/vi.h42
-rw-r--r--src/core/hle/service/vi/vi_m.cpp34
-rw-r--r--src/core/hle/service/vi/vi_m.h32
-rw-r--r--src/core/hle/service/vi/vi_s.cpp30
-rw-r--r--src/core/hle/service/vi/vi_s.h32
-rw-r--r--src/core/hle/service/vi/vi_types.h92
-rw-r--r--src/core/hle/service/vi/vi_u.cpp30
-rw-r--r--src/core/hle/service/vi/vi_u.h32
-rw-r--r--src/core/hle/service/vi/vsync_manager.cpp26
-rw-r--r--src/core/hle/service/vi/vsync_manager.h29
-rw-r--r--src/core/loader/nca.cpp4
-rw-r--r--src/core/memory.cpp8
-rw-r--r--src/core/memory/cheat_engine.cpp4
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp4
341 files changed, 14509 insertions, 11979 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2d5490968..f67a12f8f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -2,8 +2,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
add_library(core STATIC
- arm/arm_interface.h
arm/arm_interface.cpp
+ arm/arm_interface.h
arm/debug.cpp
arm/debug.h
arm/exclusive_monitor.cpp
@@ -37,10 +37,10 @@ add_library(core STATIC
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
- device_memory_manager.h
- device_memory_manager.inc
device_memory.cpp
device_memory.h
+ device_memory_manager.h
+ device_memory_manager.inc
file_sys/bis_factory.cpp
file_sys/bis_factory.h
file_sys/card_image.cpp
@@ -390,6 +390,20 @@ add_library(core STATIC
hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h
+ hle/service/am/am.cpp
+ hle/service/am/am.h
+ hle/service/am/am_results.h
+ hle/service/am/am_types.h
+ hle/service/am/applet.cpp
+ hle/service/am/applet.h
+ hle/service/am/applet_data_broker.cpp
+ hle/service/am/applet_data_broker.h
+ hle/service/am/applet_manager.cpp
+ hle/service/am/applet_manager.h
+ hle/service/am/applet_message_queue.cpp
+ hle/service/am/applet_message_queue.h
+ hle/service/am/display_layer_manager.cpp
+ hle/service/am/display_layer_manager.h
hle/service/am/frontend/applet_cabinet.cpp
hle/service/am/frontend/applet_cabinet.h
hle/service/am/frontend/applet_controller.cpp
@@ -411,80 +425,62 @@ add_library(core STATIC
hle/service/am/frontend/applet_web_browser_types.h
hle/service/am/frontend/applets.cpp
hle/service/am/frontend/applets.h
- hle/service/am/am.cpp
- hle/service/am/am.h
- hle/service/am/am_results.h
- hle/service/am/am_types.h
- hle/service/am/applet.cpp
- hle/service/am/applet.h
- hle/service/am/applet_ae.cpp
- hle/service/am/applet_ae.h
- hle/service/am/applet_manager.cpp
- hle/service/am/applet_data_broker.cpp
- hle/service/am/applet_data_broker.h
- hle/service/am/applet_manager.h
- hle/service/am/applet_oe.cpp
- hle/service/am/applet_oe.h
- hle/service/am/applet_common_functions.cpp
- hle/service/am/applet_common_functions.h
- hle/service/am/applet_message_queue.cpp
- hle/service/am/applet_message_queue.h
- hle/service/am/application_creator.cpp
- hle/service/am/application_creator.h
- hle/service/am/application_functions.cpp
- hle/service/am/application_functions.h
- hle/service/am/application_proxy.cpp
- hle/service/am/application_proxy.h
- hle/service/am/audio_controller.cpp
- hle/service/am/audio_controller.h
- hle/service/am/common_state_getter.cpp
- hle/service/am/common_state_getter.h
- hle/service/am/debug_functions.cpp
- hle/service/am/debug_functions.h
- hle/service/am/display_controller.cpp
- hle/service/am/display_controller.h
- hle/service/am/global_state_controller.cpp
- hle/service/am/global_state_controller.h
hle/service/am/hid_registration.cpp
hle/service/am/hid_registration.h
- hle/service/am/home_menu_functions.cpp
- hle/service/am/home_menu_functions.h
- hle/service/am/idle.cpp
- hle/service/am/idle.h
- hle/service/am/library_applet_accessor.cpp
- hle/service/am/library_applet_accessor.h
- hle/service/am/library_applet_creator.cpp
- hle/service/am/library_applet_creator.h
- hle/service/am/library_applet_proxy.cpp
- hle/service/am/library_applet_proxy.h
- hle/service/am/library_applet_self_accessor.cpp
- hle/service/am/library_applet_self_accessor.h
hle/service/am/library_applet_storage.cpp
hle/service/am/library_applet_storage.h
- hle/service/am/lock_accessor.cpp
- hle/service/am/lock_accessor.h
- hle/service/am/managed_layer_holder.cpp
- hle/service/am/managed_layer_holder.h
- hle/service/am/omm.cpp
- hle/service/am/omm.h
- hle/service/am/process_winding_controller.cpp
- hle/service/am/process_winding_controller.h
hle/service/am/process.cpp
hle/service/am/process.h
- hle/service/am/self_controller.cpp
- hle/service/am/self_controller.h
- hle/service/am/system_applet_proxy.cpp
- hle/service/am/system_applet_proxy.h
- hle/service/am/system_buffer_manager.cpp
- hle/service/am/system_buffer_manager.h
- hle/service/am/spsm.cpp
- hle/service/am/spsm.h
- hle/service/am/storage_accessor.cpp
- hle/service/am/storage_accessor.h
- hle/service/am/storage.cpp
- hle/service/am/storage.h
- hle/service/am/window_controller.cpp
- hle/service/am/window_controller.h
+ hle/service/am/service/all_system_applet_proxies_service.cpp
+ hle/service/am/service/all_system_applet_proxies_service.h
+ hle/service/am/service/applet_common_functions.cpp
+ hle/service/am/service/applet_common_functions.h
+ hle/service/am/service/application_accessor.cpp
+ hle/service/am/service/application_accessor.h
+ hle/service/am/service/application_creator.cpp
+ hle/service/am/service/application_creator.h
+ hle/service/am/service/application_functions.cpp
+ hle/service/am/service/application_functions.h
+ hle/service/am/service/application_proxy.cpp
+ hle/service/am/service/application_proxy.h
+ hle/service/am/service/application_proxy_service.cpp
+ hle/service/am/service/application_proxy_service.h
+ hle/service/am/service/audio_controller.cpp
+ hle/service/am/service/audio_controller.h
+ hle/service/am/service/common_state_getter.cpp
+ hle/service/am/service/common_state_getter.h
+ hle/service/am/service/cradle_firmware_updater.cpp
+ hle/service/am/service/cradle_firmware_updater.h
+ hle/service/am/service/debug_functions.cpp
+ hle/service/am/service/debug_functions.h
+ hle/service/am/service/display_controller.cpp
+ hle/service/am/service/display_controller.h
+ hle/service/am/service/global_state_controller.cpp
+ hle/service/am/service/global_state_controller.h
+ hle/service/am/service/home_menu_functions.cpp
+ hle/service/am/service/home_menu_functions.h
+ hle/service/am/service/library_applet_accessor.cpp
+ hle/service/am/service/library_applet_accessor.h
+ hle/service/am/service/library_applet_creator.cpp
+ hle/service/am/service/library_applet_creator.h
+ hle/service/am/service/library_applet_proxy.cpp
+ hle/service/am/service/library_applet_proxy.h
+ hle/service/am/service/library_applet_self_accessor.cpp
+ hle/service/am/service/library_applet_self_accessor.h
+ hle/service/am/service/lock_accessor.cpp
+ hle/service/am/service/lock_accessor.h
+ hle/service/am/service/process_winding_controller.cpp
+ hle/service/am/service/process_winding_controller.h
+ hle/service/am/service/self_controller.cpp
+ hle/service/am/service/self_controller.h
+ hle/service/am/service/storage.cpp
+ hle/service/am/service/storage.h
+ hle/service/am/service/storage_accessor.cpp
+ hle/service/am/service/storage_accessor.h
+ hle/service/am/service/system_applet_proxy.cpp
+ hle/service/am/service/system_applet_proxy.h
+ hle/service/am/service/window_controller.cpp
+ hle/service/am/service/window_controller.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp
@@ -493,12 +489,12 @@ add_library(core STATIC
hle/service/apm/apm_controller.h
hle/service/apm/apm_interface.cpp
hle/service/apm/apm_interface.h
- hle/service/audio/audctl.cpp
- hle/service/audio/audctl.h
hle/service/audio/audin_u.cpp
hle/service/audio/audin_u.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
+ hle/service/audio/audio_controller.cpp
+ hle/service/audio/audio_controller.h
hle/service/audio/audout_u.cpp
hle/service/audio/audout_u.h
hle/service/audio/audrec_a.cpp
@@ -512,18 +508,6 @@ add_library(core STATIC
hle/service/audio/hwopus.h
hle/service/bcat/backend/backend.cpp
hle/service/bcat/backend/backend.h
- hle/service/bcat/news/newly_arrived_event_holder.cpp
- hle/service/bcat/news/newly_arrived_event_holder.h
- hle/service/bcat/news/news_data_service.cpp
- hle/service/bcat/news/news_data_service.h
- hle/service/bcat/news/news_database_service.cpp
- hle/service/bcat/news/news_database_service.h
- hle/service/bcat/news/news_service.cpp
- hle/service/bcat/news/news_service.h
- hle/service/bcat/news/overwrite_event_holder.cpp
- hle/service/bcat/news/overwrite_event_holder.h
- hle/service/bcat/news/service_creator.cpp
- hle/service/bcat/news/service_creator.h
hle/service/bcat/bcat.cpp
hle/service/bcat/bcat.h
hle/service/bcat/bcat_result.h
@@ -539,6 +523,18 @@ add_library(core STATIC
hle/service/bcat/delivery_cache_progress_service.h
hle/service/bcat/delivery_cache_storage_service.cpp
hle/service/bcat/delivery_cache_storage_service.h
+ hle/service/bcat/news/newly_arrived_event_holder.cpp
+ hle/service/bcat/news/newly_arrived_event_holder.h
+ hle/service/bcat/news/news_data_service.cpp
+ hle/service/bcat/news/news_data_service.h
+ hle/service/bcat/news/news_database_service.cpp
+ hle/service/bcat/news/news_database_service.h
+ hle/service/bcat/news/news_service.cpp
+ hle/service/bcat/news/news_service.h
+ hle/service/bcat/news/overwrite_event_holder.cpp
+ hle/service/bcat/news/overwrite_event_holder.h
+ hle/service/bcat/news/service_creator.cpp
+ hle/service/bcat/news/service_creator.h
hle/service/bcat/service_creator.cpp
hle/service/bcat/service_creator.h
hle/service/bpc/bpc.cpp
@@ -547,6 +543,16 @@ add_library(core STATIC
hle/service/btdrv/btdrv.h
hle/service/btm/btm.cpp
hle/service/btm/btm.h
+ hle/service/btm/btm_debug.cpp
+ hle/service/btm/btm_debug.h
+ hle/service/btm/btm_system.cpp
+ hle/service/btm/btm_system.h
+ hle/service/btm/btm_system_core.cpp
+ hle/service/btm/btm_system_core.h
+ hle/service/btm/btm_user.cpp
+ hle/service/btm/btm_user.h
+ hle/service/btm/btm_user_core.cpp
+ hle/service/btm/btm_user_core.h
hle/service/caps/caps.cpp
hle/service/caps/caps.h
hle/service/caps/caps_a.cpp
@@ -602,8 +608,6 @@ add_library(core STATIC
hle/service/filesystem/romfs_controller.h
hle/service/filesystem/save_data_controller.cpp
hle/service/filesystem/save_data_controller.h
- hle/service/fgm/fgm.cpp
- hle/service/fgm/fgm.h
hle/service/friend/friend.cpp
hle/service/friend/friend.h
hle/service/friend/friend_interface.cpp
@@ -668,6 +672,18 @@ add_library(core STATIC
hle/service/ldn/ldn.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn_types.h
+ hle/service/ldn/monitor_service.cpp
+ hle/service/ldn/monitor_service.h
+ hle/service/ldn/sf_monitor_service.cpp
+ hle/service/ldn/sf_monitor_service.h
+ hle/service/ldn/sf_service.cpp
+ hle/service/ldn/sf_service.h
+ hle/service/ldn/sf_service_monitor.cpp
+ hle/service/ldn/sf_service_monitor.h
+ hle/service/ldn/system_local_communication_service.cpp
+ hle/service/ldn/system_local_communication_service.h
+ hle/service/ldn/user_local_communication_service.cpp
+ hle/service/ldn/user_local_communication_service.h
hle/service/ldr/ldr.cpp
hle/service/ldr/ldr.h
hle/service/lm/lm.cpp
@@ -729,15 +745,48 @@ add_library(core STATIC
hle/service/nim/nim.h
hle/service/npns/npns.cpp
hle/service/npns/npns.h
- hle/service/ns/errors.h
- hle/service/ns/iplatform_service_manager.cpp
- hle/service/ns/iplatform_service_manager.h
+ hle/service/ns/account_proxy_interface.cpp
+ hle/service/ns/account_proxy_interface.h
+ hle/service/ns/application_manager_interface.cpp
+ hle/service/ns/application_manager_interface.h
+ hle/service/ns/application_version_interface.cpp
+ hle/service/ns/application_version_interface.h
+ hle/service/ns/content_management_interface.cpp
+ hle/service/ns/content_management_interface.h
+ hle/service/ns/develop_interface.cpp
+ hle/service/ns/develop_interface.h
+ hle/service/ns/document_interface.cpp
+ hle/service/ns/document_interface.h
+ hle/service/ns/download_task_interface.cpp
+ hle/service/ns/download_task_interface.h
+ hle/service/ns/dynamic_rights_interface.cpp
+ hle/service/ns/dynamic_rights_interface.h
+ hle/service/ns/ecommerce_interface.cpp
+ hle/service/ns/ecommerce_interface.h
+ hle/service/ns/factory_reset_interface.cpp
+ hle/service/ns/factory_reset_interface.h
hle/service/ns/language.cpp
hle/service/ns/language.h
hle/service/ns/ns.cpp
hle/service/ns/ns.h
- hle/service/ns/pdm_qry.cpp
- hle/service/ns/pdm_qry.h
+ hle/service/ns/ns_results.h
+ hle/service/ns/ns_types.h
+ hle/service/ns/platform_service_manager.cpp
+ hle/service/ns/platform_service_manager.h
+ hle/service/ns/query_service.cpp
+ hle/service/ns/query_service.h
+ hle/service/ns/read_only_application_control_data_interface.cpp
+ hle/service/ns/read_only_application_control_data_interface.h
+ hle/service/ns/read_only_application_record_interface.cpp
+ hle/service/ns/read_only_application_record_interface.h
+ hle/service/ns/service_getter_interface.cpp
+ hle/service/ns/service_getter_interface.h
+ hle/service/ns/system_update_control.cpp
+ hle/service/ns/system_update_control.h
+ hle/service/ns/system_update_interface.cpp
+ hle/service/ns/system_update_interface.h
+ hle/service/ns/vulnerability_manager_interface.cpp
+ hle/service/ns/vulnerability_manager_interface.h
hle/service/nvdrv/core/container.cpp
hle/service/nvdrv/core/container.h
hle/service/nvdrv/core/heap_mapper.cpp
@@ -790,14 +839,14 @@ add_library(core STATIC
hle/service/nvnflinger/consumer_base.cpp
hle/service/nvnflinger/consumer_base.h
hle/service/nvnflinger/consumer_listener.h
- hle/service/nvnflinger/fb_share_buffer_manager.cpp
- hle/service/nvnflinger/fb_share_buffer_manager.h
hle/service/nvnflinger/graphic_buffer_producer.cpp
hle/service/nvnflinger/graphic_buffer_producer.h
- hle/service/nvnflinger/hos_binder_driver_server.cpp
- hle/service/nvnflinger/hos_binder_driver_server.h
hle/service/nvnflinger/hardware_composer.cpp
hle/service/nvnflinger/hardware_composer.h
+ hle/service/nvnflinger/hos_binder_driver.cpp
+ hle/service/nvnflinger/hos_binder_driver.h
+ hle/service/nvnflinger/hos_binder_driver_server.cpp
+ hle/service/nvnflinger/hos_binder_driver_server.h
hle/service/nvnflinger/hwc_layer.h
hle/service/nvnflinger/nvnflinger.cpp
hle/service/nvnflinger/nvnflinger.h
@@ -805,19 +854,29 @@ add_library(core STATIC
hle/service/nvnflinger/pixel_format.h
hle/service/nvnflinger/producer_listener.h
hle/service/nvnflinger/status.h
+ hle/service/nvnflinger/surface_flinger.cpp
+ hle/service/nvnflinger/surface_flinger.h
hle/service/nvnflinger/ui/fence.h
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
+ hle/service/omm/omm.cpp
+ hle/service/omm/omm.h
+ hle/service/omm/operation_mode_manager.cpp
+ hle/service/omm/operation_mode_manager.h
+ hle/service/omm/policy_manager_system.cpp
+ hle/service/omm/policy_manager_system.h
+ hle/service/omm/power_state_interface.cpp
+ hle/service/omm/power_state_interface.h
hle/service/os/event.cpp
hle/service/os/event.h
+ hle/service/os/multi_wait.cpp
+ hle/service/os/multi_wait.h
hle/service/os/multi_wait_holder.cpp
hle/service/os/multi_wait_holder.h
hle/service/os/multi_wait_utils.h
- hle/service/os/multi_wait.cpp
- hle/service/os/multi_wait.h
hle/service/os/mutex.cpp
hle/service/os/mutex.h
hle/service/pcie/pcie.cpp
@@ -855,15 +914,17 @@ add_library(core STATIC
hle/service/psc/time/common.cpp
hle/service/psc/time/common.h
hle/service/psc/time/errors.h
- hle/service/psc/time/shared_memory.cpp
- hle/service/psc/time/shared_memory.h
- hle/service/psc/time/static.cpp
- hle/service/psc/time/static.h
hle/service/psc/time/manager.h
+ hle/service/psc/time/power_state_request_manager.cpp
+ hle/service/psc/time/power_state_request_manager.h
hle/service/psc/time/power_state_service.cpp
hle/service/psc/time/power_state_service.h
hle/service/psc/time/service_manager.cpp
hle/service/psc/time/service_manager.h
+ hle/service/psc/time/shared_memory.cpp
+ hle/service/psc/time/shared_memory.h
+ hle/service/psc/time/static.cpp
+ hle/service/psc/time/static.h
hle/service/psc/time/steady_clock.cpp
hle/service/psc/time/steady_clock.h
hle/service/psc/time/system_clock.cpp
@@ -872,8 +933,6 @@ add_library(core STATIC
hle/service/psc/time/time_zone.h
hle/service/psc/time/time_zone_service.cpp
hle/service/psc/time/time_zone_service.h
- hle/service/psc/time/power_state_request_manager.cpp
- hle/service/psc/time/power_state_request_manager.h
hle/service/ptm/psm.cpp
hle/service/ptm/psm.h
hle/service/ptm/ptm.cpp
@@ -890,18 +949,21 @@ add_library(core STATIC
hle/service/server_manager.h
hle/service/service.cpp
hle/service/service.h
+ hle/service/services.cpp
+ hle/service/services.h
+ hle/service/set/factory_settings_server.cpp
+ hle/service/set/factory_settings_server.h
+ hle/service/set/firmware_debug_settings_server.cpp
+ hle/service/set/firmware_debug_settings_server.h
+ hle/service/set/key_code_map.h
hle/service/set/setting_formats/appln_settings.cpp
hle/service/set/setting_formats/appln_settings.h
hle/service/set/setting_formats/device_settings.cpp
hle/service/set/setting_formats/device_settings.h
- hle/service/set/setting_formats/system_settings.cpp
- hle/service/set/setting_formats/system_settings.h
hle/service/set/setting_formats/private_settings.cpp
hle/service/set/setting_formats/private_settings.h
- hle/service/set/factory_settings_server.cpp
- hle/service/set/factory_settings_server.h
- hle/service/set/firmware_debug_settings_server.cpp
- hle/service/set/firmware_debug_settings_server.h
+ hle/service/set/setting_formats/system_settings.cpp
+ hle/service/set/setting_formats/system_settings.h
hle/service/set/settings.cpp
hle/service/set/settings.h
hle/service/set/settings_server.cpp
@@ -936,18 +998,36 @@ add_library(core STATIC
hle/service/ssl/ssl_backend.h
hle/service/usb/usb.cpp
hle/service/usb/usb.h
- hle/service/vi/display/vi_display.cpp
- hle/service/vi/display/vi_display.h
- hle/service/vi/layer/vi_layer.cpp
- hle/service/vi/layer/vi_layer.h
+ hle/service/vi/application_display_service.cpp
+ hle/service/vi/application_display_service.h
+ hle/service/vi/application_root_service.cpp
+ hle/service/vi/application_root_service.h
+ hle/service/vi/conductor.cpp
+ hle/service/vi/conductor.h
+ hle/service/vi/container.cpp
+ hle/service/vi/container.h
+ hle/service/vi/display.h
+ hle/service/vi/display_list.h
+ hle/service/vi/layer.h
+ hle/service/vi/layer_list.h
+ hle/service/vi/manager_display_service.cpp
+ hle/service/vi/manager_display_service.h
+ hle/service/vi/manager_root_service.cpp
+ hle/service/vi/manager_root_service.h
+ hle/service/vi/service_creator.cpp
+ hle/service/vi/service_creator.h
+ hle/service/vi/shared_buffer_manager.cpp
+ hle/service/vi/shared_buffer_manager.h
+ hle/service/vi/system_display_service.cpp
+ hle/service/vi/system_display_service.h
+ hle/service/vi/system_root_service.cpp
+ hle/service/vi/system_root_service.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
- hle/service/vi/vi_m.cpp
- hle/service/vi/vi_m.h
- hle/service/vi/vi_s.cpp
- hle/service/vi/vi_s.h
- hle/service/vi/vi_u.cpp
- hle/service/vi/vi_u.h
+ hle/service/vi/vi_results.h
+ hle/service/vi/vi_types.h
+ hle/service/vi/vsync_manager.cpp
+ hle/service/vi/vsync_manager.h
internal_network/network.cpp
internal_network/network.h
internal_network/network_interface.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 435ef6793..9e8936728 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -47,6 +47,7 @@
#include "core/hle/service/psc/time/system_clock.h"
#include "core/hle/service/psc/time/time_zone_service.h"
#include "core/hle/service/service.h"
+#include "core/hle/service/services.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"
#include "core/internal_network/network.h"
@@ -242,7 +243,7 @@ struct System::Impl {
void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
- kernel.SuspendApplication(false);
+ kernel.SuspendEmulation(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
@@ -251,7 +252,7 @@ struct System::Impl {
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
- kernel.SuspendApplication(true);
+ kernel.SuspendEmulation(true);
is_paused.store(true, std::memory_order_relaxed);
}
@@ -261,7 +262,7 @@ struct System::Impl {
std::unique_lock<std::mutex> StallApplication() {
std::unique_lock<std::mutex> lk(suspend_guard);
- kernel.SuspendApplication(true);
+ kernel.SuspendEmulation(true);
core_timing.SyncPause(true);
return lk;
}
@@ -269,7 +270,7 @@ struct System::Impl {
void UnstallApplication() {
if (!IsPaused()) {
core_timing.SyncPause(false);
- kernel.SuspendApplication(false);
+ kernel.SuspendEmulation(false);
}
}
@@ -310,7 +311,8 @@ struct System::Impl {
audio_core = std::make_unique<AudioCore::AudioCore>(system);
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
- services = std::make_unique<Service::Services>(service_manager, system);
+ services =
+ std::make_unique<Service::Services>(service_manager, system, stop_event.get_token());
is_powered_on = true;
exit_locked = false;
@@ -458,11 +460,10 @@ struct System::Impl {
gpu_core->NotifyShutdown();
}
+ stop_event.request_stop();
+ core_timing.SyncPause(false);
Network::CancelPendingSocketOperations();
- kernel.SuspendApplication(true);
- if (services) {
- services->KillNVNFlinger();
- }
+ kernel.SuspendEmulation(true);
kernel.CloseServices();
kernel.ShutdownCores();
applet_manager.Reset();
@@ -480,6 +481,7 @@ struct System::Impl {
cpu_manager.Shutdown();
debugger.reset();
kernel.Shutdown();
+ stop_event = {};
Network::RestartSocketOperations();
if (auto room_member = room_network.GetRoomMember().lock()) {
@@ -615,6 +617,7 @@ struct System::Impl {
ExecuteProgramCallback execute_program_callback;
ExitCallback exit_callback;
+ std::stop_source stop_event;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 7a5c22f78..9b1c77387 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -199,10 +199,10 @@ void CpuManager::RunThread(std::stop_token token, std::size_t core) {
data.host_context = Common::Fiber::ThreadToFiber();
// Cleanup
- SCOPE_EXIT({
+ SCOPE_EXIT {
data.host_context->Exit();
MicroProfileOnThreadExit();
- });
+ };
// Running
if (!gpu_barrier->Sync(token)) {
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index d636621de..f104d495b 100644
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -391,12 +391,12 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
const auto current_vaddr =
static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
- SCOPE_EXIT({
+ SCOPE_EXIT{
page_index += next_pages;
page_offset = 0;
increment(copy_amount);
remaining_size -= copy_amount;
- });
+ };
auto phys_addr = compressed_physical_ptr[page_index];
if (phys_addr == 0) {
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 555b9d8f7..667efbbab 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -64,8 +64,8 @@ struct RawNACP {
u64_le cache_storage_size;
u64_le cache_storage_journal_size;
u64_le cache_storage_data_and_journal_max_size;
- u64_le cache_storage_max_index;
- INSERT_PADDING_BYTES(0xE70);
+ u16_le cache_storage_max_index;
+ INSERT_PADDING_BYTES(0xE76);
};
static_assert(sizeof(RawNACP) == 0x4000, "RawNACP has incorrect size.");
diff --git a/src/core/file_sys/fs_directory.h b/src/core/file_sys/fs_directory.h
index 25c9cb18a..3f90abb8f 100644
--- a/src/core/file_sys/fs_directory.h
+++ b/src/core/file_sys/fs_directory.h
@@ -3,6 +3,10 @@
#pragma once
+#include <string_view>
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+
namespace FileSys {
constexpr inline size_t EntryNameLengthMax = 0x300;
diff --git a/src/core/file_sys/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h
index e9011d065..5643141f9 100644
--- a/src/core/file_sys/fs_path_utility.h
+++ b/src/core/file_sys/fs_path_utility.h
@@ -447,7 +447,7 @@ public:
char* replacement_path = nullptr;
size_t replacement_path_size = 0;
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (replacement_path != nullptr) {
if (std::is_constant_evaluated()) {
delete[] replacement_path;
@@ -455,7 +455,7 @@ public:
Deallocate(replacement_path, replacement_path_size);
}
}
- });
+ };
// Perform path replacement, if necessary
if (IsParentDirectoryPathReplacementNeeded(cur_path)) {
@@ -1102,8 +1102,8 @@ public:
R_SUCCEED();
}
- static Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len,
- const PathFlags& flags) {
+ static constexpr Result Normalize(char* dst, size_t dst_size, const char* path, size_t path_len,
+ const PathFlags& flags) {
// Use StringTraits names for remainder of scope
using namespace StringTraits;
@@ -1199,7 +1199,7 @@ public:
const size_t replaced_src_len = path_len - (src - path);
char* replaced_src = nullptr;
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (replaced_src != nullptr) {
if (std::is_constant_evaluated()) {
delete[] replaced_src;
@@ -1207,7 +1207,7 @@ public:
Deallocate(replaced_src, replaced_src_len);
}
}
- });
+ };
if (std::is_constant_evaluated()) {
replaced_src = new char[replaced_src_len];
diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
index f342efb57..0e83ca1b9 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
@@ -3,6 +3,7 @@
#pragma once
+#include <mutex>
#include <optional>
#include "core/crypto/aes_util.h"
diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp
index caea0b8f8..a68fd973c 100644
--- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp
@@ -36,7 +36,9 @@ Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 lay
// Get the base storage size.
m_base_storage_size = base_storages[2]->GetSize();
{
- auto size_guard = SCOPE_GUARD({ m_base_storage_size = 0; });
+ auto size_guard = SCOPE_GUARD {
+ m_base_storage_size = 0;
+ };
R_UNLESS(m_base_storage_size <= static_cast<s64>(HashSize)
<< m_log_size_ratio << m_log_size_ratio,
ResultHierarchicalSha256BaseStorageTooLarge);
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index ae4e441c9..289969cc4 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -98,7 +98,9 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
Loader::ResultStatus ProgramMetadata::Reload(VirtualFile file) {
const u64 original_program_id = aci_header.title_id;
- SCOPE_EXIT({ aci_header.title_id = original_program_id; });
+ SCOPE_EXIT {
+ aci_header.title_id = original_program_id;
+ };
return this->Load(file);
}
diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp
index deb52069d..9ea16aa59 100644
--- a/src/core/file_sys/system_archive/shared_font.cpp
+++ b/src/core/file_sys/system_archive/shared_font.cpp
@@ -9,7 +9,7 @@
#include "core/file_sys/system_archive/data/font_standard.h"
#include "core/file_sys/system_archive/shared_font.h"
#include "core/file_sys/vfs/vfs_vector.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
+#include "core/hle/service/ns/platform_service_manager.h"
namespace FileSys::SystemArchive {
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 8f90eba34..8c4e14f08 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -2,25 +2,19 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/am/am.h"
-#include "core/hle/service/am/applet_ae.h"
-#include "core/hle/service/am/applet_oe.h"
-#include "core/hle/service/am/idle.h"
-#include "core/hle/service/am/omm.h"
-#include "core/hle/service/am/spsm.h"
+#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
+#include "core/hle/service/am/service/application_proxy_service.h"
#include "core/hle/service/server_manager.h"
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<AppletAE>(nvnflinger, system));
+ std::make_shared<IAllSystemAppletProxiesService>(system));
server_manager->RegisterNamedService("appletOE",
- std::make_shared<AppletOE>(nvnflinger, system));
- server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
- server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
- server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
+ 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/am_types.h b/src/core/hle/service/am/am_types.h
index 8c33feb15..46afb3996 100644
--- a/src/core/hle/service/am/am_types.h
+++ b/src/core/hle/service/am/am_types.h
@@ -18,7 +18,7 @@ enum class AppletType {
SystemApplet,
};
-enum class GameplayRecordingState : u32 {
+enum class GamePlayRecordingState : u32 {
Disabled,
Enabled,
};
@@ -67,10 +67,9 @@ enum class ScreenshotPermission : u32 {
};
struct FocusHandlingMode {
- bool unknown0;
- bool unknown1;
- bool unknown2;
- bool unknown3;
+ bool notify;
+ bool background;
+ bool suspend;
};
enum class IdleTimeDetectionExtension : u32 {
@@ -128,6 +127,40 @@ enum class AppletProgramId : u64 {
MaxProgramId = 0x0100000000001FFFull,
};
+// This is nn::am::AppletMessage
+enum class AppletMessage : u32 {
+ None = 0,
+ ChangeIntoForeground = 1,
+ ChangeIntoBackground = 2,
+ Exit = 4,
+ ApplicationExited = 6,
+ FocusStateChanged = 15,
+ Resume = 16,
+ DetectShortPressingHomeButton = 20,
+ DetectLongPressingHomeButton = 21,
+ DetectShortPressingPowerButton = 22,
+ DetectMiddlePressingPowerButton = 23,
+ DetectLongPressingPowerButton = 24,
+ RequestToPrepareSleep = 25,
+ FinishedSleepSequence = 26,
+ SleepRequiredByHighTemperature = 27,
+ SleepRequiredByLowBattery = 28,
+ AutoPowerDown = 29,
+ OperationModeChanged = 30,
+ PerformanceModeChanged = 31,
+ DetectReceivingCecSystemStandby = 32,
+ SdCardRemoved = 33,
+ LaunchApplicationRequested = 50,
+ RequestToDisplay = 51,
+ ShowApplicationLogo = 55,
+ HideApplicationLogo = 56,
+ ForceHideApplicationLogo = 57,
+ FloatingApplicationDetected = 60,
+ DetectShortPressingCaptureButton = 90,
+ AlbumScreenShotTaken = 92,
+ AlbumRecordingSaved = 93,
+};
+
enum class LibraryAppletMode : u32 {
AllForeground = 0,
PartialForeground = 1,
@@ -136,6 +169,11 @@ enum class LibraryAppletMode : u32 {
AllForegroundInitiallyHidden = 4,
};
+enum class LaunchParameterKind : u32 {
+ UserChannel = 1,
+ AccountPreselectedUser = 2,
+};
+
enum class CommonArgumentVersion : u32 {
Version0,
Version1,
@@ -152,6 +190,22 @@ enum class ThemeColor : u32 {
BasicBlack = 3,
};
+enum class InputDetectionPolicy : u32 {
+ Unknown0 = 0,
+ Unknown1 = 1,
+};
+
+enum class WindowOriginMode : u32 {
+ LowerLeft = 0,
+ UpperLeft = 1,
+};
+
+enum class ProgramSpecifyKind : u32 {
+ ExecuteProgram = 0,
+ JumpToSubApplicationProgramForDevelopment = 1,
+ RestartProgram = 2,
+};
+
struct CommonArguments {
CommonArgumentVersion arguments_version;
CommonArgumentSize size;
@@ -169,6 +223,27 @@ struct AppletIdentityInfo {
};
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
+struct AppletAttribute {
+ u8 flag;
+ INSERT_PADDING_BYTES_NOINIT(0x7F);
+};
+static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size.");
+
+// This is nn::oe::DisplayVersion
+struct DisplayVersion {
+ std::array<char, 0x10> string;
+};
+static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size.");
+
+// This is nn::pdm::ApplicationPlayStatistics
+struct ApplicationPlayStatistics {
+ u64 application_id;
+ u64 play_time_ns;
+ u64 launch_count;
+};
+static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
+ "ApplicationPlayStatistics has incorrect size.");
+
using AppletResourceUserId = u64;
using ProgramId = u64;
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
index b29ecdfed..ad602153e 100644
--- a/src/core/hle/service/am/applet.h
+++ b/src/core/hle/service/am/applet.h
@@ -3,7 +3,6 @@
#pragma once
-#include <list>
#include <mutex>
#include "common/math_util.h"
@@ -15,11 +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/storage.h"
-#include "core/hle/service/am/system_buffer_manager.h"
namespace Service::AM {
@@ -56,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{};
@@ -76,8 +72,8 @@ struct Applet {
u32 application_core_usage_mode{};
// Application functions
- bool gameplay_recording_supported{};
- GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled};
+ bool game_play_recording_supported{};
+ GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
bool jit_service_launched{};
bool is_running{};
bool application_crash_report_enabled{};
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
deleted file mode 100644
index 1b715dea6..000000000
--- a/src/core/hle/service/am/applet_ae.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet_ae.h"
-#include "core/hle/service/am/applet_manager.h"
-#include "core/hle/service/am/library_applet_proxy.h"
-#include "core/hle/service/am/system_applet_proxy.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
- : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
- {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"},
- {201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"},
- {300, nullptr, "OpenOverlayAppletProxy"},
- {350, nullptr, "OpenSystemApplicationProxy"},
- {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
- {410, nullptr, "GetSystemAppletControllerForDebug"},
- {1000, nullptr, "GetDebugFunctions"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-AppletAE::~AppletAE() = default;
-
-void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- if (const auto applet = GetAppletFromContext(ctx)) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, applet, system);
- } else {
- UNIMPLEMENTED();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- }
-}
-
-void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- if (const auto applet = GetAppletFromContext(ctx)) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, applet, system);
- } else {
- UNIMPLEMENTED();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- }
-}
-
-void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- return OpenLibraryAppletProxy(ctx);
-}
-
-std::shared_ptr<Applet> AppletAE::GetAppletFromContext(HLERequestContext& ctx) {
- const auto aruid = ctx.GetPID();
- return system.GetAppletManager().GetByAppletResourceUserId(aruid);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
deleted file mode 100644
index 3d7961fa1..000000000
--- a/src/core/hle/service/am/applet_ae.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace FileSystem {
-class FileSystemController;
-}
-
-namespace Nvnflinger {
-class Nvnflinger;
-}
-
-namespace AM {
-
-struct Applet;
-
-class AppletAE final : public ServiceFramework<AppletAE> {
-public:
- explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
- ~AppletAE() override;
-
-private:
- void OpenSystemAppletProxy(HLERequestContext& ctx);
- void OpenLibraryAppletProxy(HLERequestContext& ctx);
- void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
-
- std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-} // namespace AM
-} // namespace Service
diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp
deleted file mode 100644
index 130614ae5..000000000
--- a/src/core/hle/service/am/applet_common_functions.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet.h"
-#include "core/hle/service/am/applet_common_functions.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
- std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "SetTerminateResult"},
- {10, nullptr, "ReadThemeStorage"},
- {11, nullptr, "WriteThemeStorage"},
- {20, nullptr, "PushToAppletBoundChannel"},
- {21, nullptr, "TryPopFromAppletBoundChannel"},
- {40, nullptr, "GetDisplayLogicalResolution"},
- {42, nullptr, "SetDisplayMagnification"},
- {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
- {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
- {52, nullptr, "IsHomeButtonShortPressedBlocked"},
- {60, nullptr, "IsVrModeCurtainRequired"},
- {61, nullptr, "IsSleepRequiredByHighTemperature"},
- {62, nullptr, "IsSleepRequiredByLowBattery"},
- {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
- {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
- {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
- {90, nullptr, "OpenNamedChannelAsParent"},
- {91, nullptr, "OpenNamedChannelAsChild"},
- {100, nullptr, "SetApplicationCoreUsageMode"},
- {300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IAppletCommonFunctions::~IAppletCommonFunctions() = default;
-
-void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
-
- std::scoped_lock lk{applet->lock};
- applet->cpu_boost_request_priority = rp.Pop<s32>();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetApplicationProcessProgramID() & ~0xFFFULL);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h
deleted file mode 100644
index b86adf5cb..000000000
--- a/src/core/hle/service/am/applet_common_functions.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
-public:
- explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~IAppletCommonFunctions() override;
-
-private:
- void SetCpuBoostRequestPriority(HLERequestContext& ctx);
- void GetCurrentApplicationId(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
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 52200d5b2..2e109181d 100644
--- a/src/core/hle/service/am/applet_manager.cpp
+++ b/src/core/hle/service/am/applet_manager.cpp
@@ -12,6 +12,7 @@
#include "core/hle/service/am/frontend/applet_controller.h"
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
+#include "core/hle/service/am/service/storage.h"
#include "hid_core/hid_types.h"
namespace Service::AM {
@@ -34,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,
@@ -283,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;
@@ -303,8 +322,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
}
// Applet was started by frontend, so it is foreground.
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
+ applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
+ applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
applet->focus_state = FocusState::InFocus;
this->InsertApplet(std::move(applet));
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp
index 5ed996b70..83c3c5a55 100644
--- a/src/core/hle/service/am/applet_message_queue.cpp
+++ b/src/core/hle/service/am/applet_message_queue.cpp
@@ -33,7 +33,7 @@ void AppletMessageQueue::PushMessage(AppletMessage msg) {
on_new_message->Signal();
}
-AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
+AppletMessage AppletMessageQueue::PopMessage() {
std::scoped_lock lk{lock};
if (messages.empty()) {
on_new_message->Clear();
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h
index 5cb236d47..429b77d37 100644
--- a/src/core/hle/service/am/applet_message_queue.h
+++ b/src/core/hle/service/am/applet_message_queue.h
@@ -5,6 +5,7 @@
#include <queue>
+#include "core/hle/service/am/am_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
@@ -16,40 +17,6 @@ namespace Service::AM {
class AppletMessageQueue {
public:
- // This is nn::am::AppletMessage
- enum class AppletMessage : u32 {
- None = 0,
- ChangeIntoForeground = 1,
- ChangeIntoBackground = 2,
- Exit = 4,
- ApplicationExited = 6,
- FocusStateChanged = 15,
- Resume = 16,
- DetectShortPressingHomeButton = 20,
- DetectLongPressingHomeButton = 21,
- DetectShortPressingPowerButton = 22,
- DetectMiddlePressingPowerButton = 23,
- DetectLongPressingPowerButton = 24,
- RequestToPrepareSleep = 25,
- FinishedSleepSequence = 26,
- SleepRequiredByHighTemperature = 27,
- SleepRequiredByLowBattery = 28,
- AutoPowerDown = 29,
- OperationModeChanged = 30,
- PerformanceModeChanged = 31,
- DetectReceivingCecSystemStandby = 32,
- SdCardRemoved = 33,
- LaunchApplicationRequested = 50,
- RequestToDisplay = 51,
- ShowApplicationLogo = 55,
- HideApplicationLogo = 56,
- ForceHideApplicationLogo = 57,
- FloatingApplicationDetected = 60,
- DetectShortPressingCaptureButton = 90,
- AlbumScreenShotTaken = 92,
- AlbumRecordingSaved = 93,
- };
-
explicit AppletMessageQueue(Core::System& system);
~AppletMessageQueue();
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
deleted file mode 100644
index 56bafd162..000000000
--- a/src/core/hle/service/am/applet_oe.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/am.h"
-#include "core/hle/service/am/applet_manager.h"
-#include "core/hle/service/am/applet_oe.h"
-#include "core/hle/service/am/application_proxy.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
- : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} {
- static const FunctionInfo functions[] = {
- {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
- };
- RegisterHandlers(functions);
-}
-
-AppletOE::~AppletOE() = default;
-
-void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- if (const auto applet = GetAppletFromContext(ctx)) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationProxy>(nvnflinger, applet, system);
- } else {
- UNIMPLEMENTED();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- }
-}
-
-std::shared_ptr<Applet> AppletOE::GetAppletFromContext(HLERequestContext& ctx) {
- const auto aruid = ctx.GetPID();
- return system.GetAppletManager().GetByAppletResourceUserId(aruid);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
deleted file mode 100644
index f2ba1c924..000000000
--- a/src/core/hle/service/am/applet_oe.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-
-#include "core/hle/service/service.h"
-
-namespace Service {
-namespace FileSystem {
-class FileSystemController;
-}
-
-namespace Nvnflinger {
-class Nvnflinger;
-}
-
-namespace AM {
-
-struct Applet;
-
-class AppletOE final : public ServiceFramework<AppletOE> {
-public:
- explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
- ~AppletOE() override;
-
-private:
- void OpenApplicationProxy(HLERequestContext& ctx);
-
- std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-} // namespace AM
-} // namespace Service
diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp
deleted file mode 100644
index 79ea045a3..000000000
--- a/src/core/hle/service/am/application_creator.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/application_creator.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IApplicationCreator::IApplicationCreator(Core::System& system_)
- : ServiceFramework{system_, "IApplicationCreator"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "CreateApplication"},
- {1, nullptr, "PopLaunchRequestedApplication"},
- {10, nullptr, "CreateSystemApplication"},
- {100, nullptr, "PopFloatingApplicationForDevelopment"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationCreator::~IApplicationCreator() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h
deleted file mode 100644
index 375a3c476..000000000
--- a/src/core/hle/service/am/application_creator.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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::AM {
-
-class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
-public:
- explicit IApplicationCreator(Core::System& system_);
- ~IApplicationCreator() override;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp
deleted file mode 100644
index 51c5be2d1..000000000
--- a/src/core/hle/service/am/application_functions.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/settings.h"
-#include "common/uuid.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/file_sys/registered_cache.h"
-#include "core/file_sys/savedata_factory.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/applet.h"
-#include "core/hle/service/am/application_functions.h"
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/filesystem/save_data_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/sm/sm.h"
-
-namespace Service::AM {
-
-enum class LaunchParameterKind : u32 {
- UserChannel = 1,
- AccountPreselectedUser = 2,
-};
-
-IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
- {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
- {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
- {12, nullptr, "CreateApplicationAndRequestToStart"},
- {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
- {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
- {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
- {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
- {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
- {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
- {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
- {24, nullptr, "GetLaunchStorageInfoForDebug"},
- {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
- {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
- {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
- {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
- {29, nullptr, "GetCacheStorageMax"},
- {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
- {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
- {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
- {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
- {34, nullptr, "SelectApplicationLicense"},
- {35, nullptr, "GetDeviceSaveDataSizeMax"},
- {36, nullptr, "GetLimitedApplicationLicense"},
- {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
- {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
- {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
- {60, nullptr, "SetMediaPlaybackStateForApplication"},
- {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
- {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
- {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
- {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
- {70, nullptr, "RequestToShutdown"},
- {71, nullptr, "RequestToReboot"},
- {72, nullptr, "RequestToSleep"},
- {80, nullptr, "ExitAndRequestToShowThanksMessage"},
- {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
- {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
- {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
- {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
- {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
- {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
- {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
- {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
- {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
- {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
- {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
- {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
- {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
- {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
- {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
- {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
- {151, nullptr, "TryPopFromNotificationStorageChannel"},
- {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
- {170, nullptr, "SetHdcpAuthenticationActivated"},
- {180, nullptr, "GetLaunchRequiredVersion"},
- {181, nullptr, "UpgradeLaunchRequiredVersion"},
- {190, nullptr, "SendServerMaintenanceOverlayNotification"},
- {200, nullptr, "GetLastApplicationExitReason"},
- {500, nullptr, "StartContinuousRecordingFlushForDebug"},
- {1000, nullptr, "CreateMovieMaker"},
- {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationFunctions::~IApplicationFunctions() = default;
-
-void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->application_crash_report_enabled = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto is_visible = rp.Pop<bool>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->home_button_long_pressed_blocked = true;
- applet->home_button_short_pressed_blocked = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->home_button_long_pressed_blocked = false;
- applet->home_button_short_pressed_blocked = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->home_button_long_pressed_blocked = true;
- applet->home_button_short_pressed_blocked = true;
- applet->home_button_double_click_enabled = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->home_button_long_pressed_blocked = false;
- applet->home_button_short_pressed_blocked = false;
- applet->home_button_double_click_enabled = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto kind = rp.PopEnum<LaunchParameterKind>();
-
- LOG_INFO(Service_AM, "called, kind={:08X}", kind);
-
- std::scoped_lock lk{applet->lock};
-
- auto& channel = kind == LaunchParameterKind::UserChannel
- ? applet->user_channel_launch_parameter
- : applet->preselected_user_launch_parameter;
-
- if (channel.empty()) {
- LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultNoDataInChannel);
- return;
- }
-
- auto data = channel.back();
- channel.pop_back();
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorage>(system, std::move(data));
-}
-
-void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- u128 user_id = rp.PopRaw<u128>();
-
- LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
-
- FileSys::SaveDataAttribute attribute{};
- attribute.title_id = applet->program_id;
- attribute.user_id = user_id;
- attribute.type = FileSys::SaveDataType::SaveData;
-
- FileSys::VirtualDir save_data{};
- const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
- &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
- // Takes an input u32 Result, no output.
- // For example, in some cases official apps use this with error 0x2A2 then
- // uses svcBreak.
-
- IPC::RequestParser rp{ctx};
- u32 result = rp.Pop<u32>();
- LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
-
- std::scoped_lock lk{applet->lock};
- applet->terminate_result = Result(result);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- std::array<u8, 0x10> version_string{};
-
- const auto res = [this] {
- const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
- system.GetContentProvider()};
- auto metadata = pm.GetControlMetadata();
- if (metadata.first != nullptr) {
- return metadata;
- }
-
- const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
- system.GetFileSystemController(),
- system.GetContentProvider()};
- return pm_update.GetControlMetadata();
- }();
-
- if (res.first != nullptr) {
- const auto& version = res.first->GetVersionString();
- std::copy(version.begin(), version.end(), version_string.begin());
- } else {
- static constexpr char default_version[]{"1.0.0"};
- std::memcpy(version_string.data(), default_version, sizeof(default_version));
- }
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(version_string);
-}
-
-void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
- // TODO(bunnei): This should be configurable
- LOG_DEBUG(Service_AM, "called");
-
- // Get supported languages from NACP, if possible
- // Default to 0 (all languages supported)
- u32 supported_languages = 0;
-
- const auto res = [this] {
- const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
- system.GetContentProvider()};
- auto metadata = pm.GetControlMetadata();
- if (metadata.first != nullptr) {
- return metadata;
- }
-
- const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
- system.GetFileSystemController(),
- system.GetContentProvider()};
- return pm_update.GetControlMetadata();
- }();
-
- if (res.first != nullptr) {
- supported_languages = res.first->GetSupportedLanguages();
- }
-
- // Call IApplicationManagerInterface implementation.
- auto& service_manager = system.ServiceManager();
- auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
-
- // Get desired application language
- u8 desired_language{};
- const auto res_lang =
- app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
- if (res_lang != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res_lang);
- return;
- }
-
- // Convert to settings language code.
- u64 language_code{};
- const auto res_code =
- app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
- if (res_code != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res_code);
- return;
- }
-
- LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(language_code);
-}
-
-void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(applet->gameplay_recording_supported);
-}
-
-void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
-
- std::scoped_lock lk{applet->lock};
- applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->is_running = true;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
-}
-
-void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
-
- // Returns a 128-bit UUID
- rb.Push<u64>(0);
- rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
- struct Parameters {
- FileSys::SaveDataType type;
- u128 user_id;
- u64 new_normal_size;
- u64 new_journal_size;
- };
- static_assert(sizeof(Parameters) == 40);
-
- IPC::RequestParser rp{ctx};
- const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_AM,
- "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
- "new_journal={:016X}",
- static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
-
- system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
- type, applet->program_id, user_id, {new_normal_size, new_journal_size});
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
-
- // The following value is used upon failure to help the system recover.
- // Since we always succeed, this should be 0.
- rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
- struct Parameters {
- FileSys::SaveDataType type;
- u128 user_id;
- };
- static_assert(sizeof(Parameters) == 24);
-
- IPC::RequestParser rp{ctx};
- const auto [type, user_id] = rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
- user_id[0]);
-
- const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
- type, applet->program_id, user_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(size.normal);
- rb.Push(size.journal);
-}
-
-void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
- struct InputParameters {
- u16 index;
- s64 size;
- s64 journal_size;
- };
- static_assert(sizeof(InputParameters) == 24);
-
- struct OutputParameters {
- u32 storage_target;
- u64 required_size;
- };
- static_assert(sizeof(OutputParameters) == 16);
-
- IPC::RequestParser rp{ctx};
- const auto params = rp.PopRaw<InputParameters>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
- params.index, params.size, params.journal_size);
-
- const OutputParameters resp{
- .storage_target = 1,
- .required_size = 0,
- };
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(resp);
-}
-
-void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- constexpr u64 size_max_normal = 0xFFFFFFF;
- constexpr u64 size_max_journal = 0xFFFFFFF;
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(size_max_normal);
- rb.Push(size_max_journal);
-}
-
-void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(0);
-}
-
-void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(0);
-}
-
-void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
- [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
- [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
- const auto program_index = rp.Pop<u64>();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-
- // Swap user channel ownership into the system so that it will be preserved
- system.GetUserChannel().swap(applet->user_channel_launch_parameter);
- system.ExecuteProgram(program_index);
-}
-
-void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- applet->user_channel_launch_parameter.clear();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- const auto storage = rp.PopIpcInterface<IStorage>().lock();
- if (storage) {
- applet->user_channel_launch_parameter.push_back(storage->GetData());
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<s32>(applet->previous_program_index);
-}
-
-void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle());
-}
-
-void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
-}
-
-void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultNoDataInChannel);
-}
-
-void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle());
-}
-
-void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
-}
-
-void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->jit_service_launched = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h
deleted file mode 100644
index 55eb21d39..000000000
--- a/src/core/hle/service/am/application_functions.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-struct Applet;
-
-class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
-public:
- explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~IApplicationFunctions() override;
-
-private:
- void PopLaunchParameter(HLERequestContext& ctx);
- void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
- void EnsureSaveData(HLERequestContext& ctx);
- void SetTerminateResult(HLERequestContext& ctx);
- void GetDisplayVersion(HLERequestContext& ctx);
- void GetDesiredLanguage(HLERequestContext& ctx);
- void IsGamePlayRecordingSupported(HLERequestContext& ctx);
- void InitializeGamePlayRecording(HLERequestContext& ctx);
- void SetGamePlayRecordingState(HLERequestContext& ctx);
- void NotifyRunning(HLERequestContext& ctx);
- void GetPseudoDeviceId(HLERequestContext& ctx);
- void ExtendSaveData(HLERequestContext& ctx);
- void GetSaveDataSize(HLERequestContext& ctx);
- void CreateCacheStorage(HLERequestContext& ctx);
- void GetSaveDataSizeMax(HLERequestContext& ctx);
- void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
- void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
- void BeginBlockingHomeButton(HLERequestContext& ctx);
- void EndBlockingHomeButton(HLERequestContext& ctx);
- void EnableApplicationCrashReport(HLERequestContext& ctx);
- void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
- void SetApplicationCopyrightImage(HLERequestContext& ctx);
- void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
- void QueryApplicationPlayStatistics(HLERequestContext& ctx);
- void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
- void ExecuteProgram(HLERequestContext& ctx);
- void ClearUserChannel(HLERequestContext& ctx);
- void UnpopToUserChannel(HLERequestContext& ctx);
- void GetPreviousProgramIndex(HLERequestContext& ctx);
- void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
- void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
- void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
- void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
- void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
- void PrepareForJit(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp
deleted file mode 100644
index a6fd6d37f..000000000
--- a/src/core/hle/service/am/application_proxy.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet_common_functions.h"
-#include "core/hle/service/am/application_functions.h"
-#include "core/hle/service/am/application_proxy.h"
-#include "core/hle/service/am/audio_controller.h"
-#include "core/hle/service/am/common_state_getter.h"
-#include "core/hle/service/am/debug_functions.h"
-#include "core/hle/service/am/display_controller.h"
-#include "core/hle/service/am/library_applet_creator.h"
-#include "core/hle/service/am/library_applet_self_accessor.h"
-#include "core/hle/service/am/process_winding_controller.h"
-#include "core/hle/service/am/self_controller.h"
-#include "core/hle/service/am/window_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> applet_, Core::System& system_)
- : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
- applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
- {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
- {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
- {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
- {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
- {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"},
- {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
- {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
- {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationProxy::~IApplicationProxy() = default;
-
-void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioController>(system);
-}
-
-void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDisplayController>(system, applet);
-}
-
-void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IProcessWindingController>(system, applet);
-}
-
-void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDebugFunctions>(system);
-}
-
-void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IWindowController>(system, applet);
-}
-
-void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
-}
-
-void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ICommonStateGetter>(system, applet);
-}
-
-void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
-}
-
-void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationFunctions>(system, applet);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h
deleted file mode 100644
index eb98b095c..000000000
--- a/src/core/hle/service/am/application_proxy.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
-public:
- explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> msg_queue_, Core::System& system_);
- ~IApplicationProxy();
-
-private:
- void GetAudioController(HLERequestContext& ctx);
- void GetDisplayController(HLERequestContext& ctx);
- void GetProcessWindingController(HLERequestContext& ctx);
- void GetDebugFunctions(HLERequestContext& ctx);
- void GetWindowController(HLERequestContext& ctx);
- void GetSelfController(HLERequestContext& ctx);
- void GetCommonStateGetter(HLERequestContext& ctx);
- void GetLibraryAppletCreator(HLERequestContext& ctx);
- void GetApplicationFunctions(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nvnflinger;
- std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp
deleted file mode 100644
index ae75db174..000000000
--- a/src/core/hle/service/am/audio_controller.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/audio_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IAudioController::IAudioController(Core::System& system_)
- : ServiceFramework{system_, "IAudioController"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
- {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
- {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
- {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
- {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IAudioController::~IAudioController() = default;
-
-void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const float main_applet_volume_tmp = rp.Pop<float>();
- const float library_applet_volume_tmp = rp.Pop<float>();
-
- LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
- main_applet_volume_tmp, library_applet_volume_tmp);
-
- // Ensure the volume values remain within the 0-100% range
- main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
- library_applet_volume =
- std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(main_applet_volume);
-}
-
-void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(library_applet_volume);
-}
-
-void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
- struct Parameters {
- float volume;
- s64 fade_time_ns;
- };
- static_assert(sizeof(Parameters) == 16);
-
- IPC::RequestParser rp{ctx};
- const auto parameters = rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
- parameters.fade_time_ns);
-
- main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
- fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const float transparent_volume_rate_tmp = rp.Pop<float>();
-
- LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
-
- // Clamp volume range to 0-100%.
- transparent_volume_rate =
- std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h
deleted file mode 100644
index a47e3bad8..000000000
--- a/src/core/hle/service/am/audio_controller.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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::AM {
-
-class IAudioController final : public ServiceFramework<IAudioController> {
-public:
- explicit IAudioController(Core::System& system_);
- ~IAudioController() override;
-
-private:
- void SetExpectedMasterVolume(HLERequestContext& ctx);
- void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
- void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
- void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
- void SetTransparentAudioRate(HLERequestContext& ctx);
-
- static constexpr float min_allowed_volume = 0.0f;
- static constexpr float max_allowed_volume = 1.0f;
-
- float main_applet_volume{0.25f};
- float library_applet_volume{max_allowed_volume};
- float transparent_volume_rate{min_allowed_volume};
-
- // Volume transition fade time in nanoseconds.
- // e.g. If the main applet volume was 0% and was changed to 50%
- // with a fade of 50ns, then over the course of 50ns,
- // the volume will gradually fade up to 50%
- std::chrono::nanoseconds fade_time_ns{0};
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp
deleted file mode 100644
index 937ac0beb..000000000
--- a/src/core/hle/service/am/common_state_getter.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/settings.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/applet.h"
-#include "core/hle/service/am/common_state_getter.h"
-#include "core/hle/service/am/lock_accessor.h"
-#include "core/hle/service/apm/apm_controller.h"
-#include "core/hle/service/apm/apm_interface.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/pm/pm.h"
-#include "core/hle/service/sm/sm.h"
-#include "core/hle/service/vi/vi.h"
-
-namespace Service::AM {
-
-ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
- {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
- {2, nullptr, "GetThisAppletKind"},
- {3, nullptr, "AllowToEnterSleep"},
- {4, nullptr, "DisallowToEnterSleep"},
- {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
- {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
- {7, nullptr, "GetCradleStatus"},
- {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
- {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
- {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
- {11, nullptr, "ReleaseSleepLock"},
- {12, nullptr, "ReleaseSleepLockTransiently"},
- {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
- {14, nullptr, "GetWakeupCount"},
- {20, nullptr, "PushToGeneralChannel"},
- {30, nullptr, "GetHomeButtonReaderLockAccessor"},
- {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
- {32, nullptr, "GetWriterLockAccessorEx"},
- {40, nullptr, "GetCradleFwVersion"},
- {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
- {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
- {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
- {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
- {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
- {55, nullptr, "IsInControllerFirmwareUpdateSection"},
- {59, nullptr, "SetVrPositionForDebug"},
- {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
- {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
- {62, nullptr, "GetHdcpAuthenticationState"},
- {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
- {64, nullptr, "SetTvPowerStateMatchingMode"},
- {65, nullptr, "GetApplicationIdByContentActionName"},
- {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
- {67, nullptr, "CancelCpuBoostMode"},
- {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
- {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
- {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
- {91, nullptr, "GetCurrentPerformanceConfiguration"},
- {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
- {110, nullptr, "OpenMyGpuErrorHandler"},
- {120, &ICommonStateGetter::GetAppletLaunchedHistory, "GetAppletLaunchedHistory"},
- {200, nullptr, "GetOperationModeSystemInfo"},
- {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
- {400, nullptr, "ActivateMigrationService"},
- {401, nullptr, "DeactivateMigrationService"},
- {500, nullptr, "DisableSleepTillShutdown"},
- {501, nullptr, "SuppressDisablingSleepTemporarily"},
- {502, nullptr, "IsSleepEnabled"},
- {503, nullptr, "IsDisablingSleepSuppressed"},
- {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-ICommonStateGetter::~ICommonStateGetter() = default;
-
-void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
-}
-
-void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent());
-}
-
-void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- const auto message = applet->message_queue.PopMessage();
- IPC::ResponseBuilder rb{ctx, 3};
-
- if (message == AppletMessageQueue::AppletMessage::None) {
- LOG_ERROR(Service_AM, "Message queue is empty");
- rb.Push(AM::ResultNoMessages);
- rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
- return;
- }
-
- rb.Push(ResultSuccess);
- rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
-}
-
-void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u8>(applet->focus_state));
-}
-
-void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
- const bool use_docked_mode{Settings::IsDockedMode()};
- LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
-}
-
-void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
-}
-
-void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- // Sleep lock is acquired immediately.
- applet->sleep_lock_event.Signal();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto unknown = rp.Pop<u32>();
-
- LOG_INFO(Service_AM, "called, unknown={}", unknown);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILockAccessor>(system);
-}
-
-void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->sleep_lock_event.GetHandle());
-}
-
-void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- std::scoped_lock lk{applet->lock};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(applet->vr_mode_enabled);
-}
-
-void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- std::scoped_lock lk{applet->lock};
- applet->vr_mode_enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
- is_lcd_backlight_off_enabled);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->vr_mode_enabled = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->vr_mode_enabled = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent());
-}
-
-void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
-
- if (Settings::IsDockedMode()) {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
- } else {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
- }
-}
-
-void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
-
- const auto& sm = system.ServiceManager();
- const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
- ASSERT(apm_sys != nullptr);
-
- apm_sys->SetCpuBoostMode(ctx);
-}
-
-void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
-}
-
-void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto system_button{rp.PopEnum<SystemButtonType>()};
-
- LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetAppletLaunchedHistory(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::shared_ptr<Applet> current_applet = applet;
- std::vector<AppletId> result;
-
- const size_t count = ctx.GetWriteBufferNumElements<AppletId>();
- size_t i;
-
- for (i = 0; i < count && current_applet != nullptr; i++) {
- result.push_back(current_applet->applet_id);
- current_applet = current_applet->caller_applet.lock();
- }
-
- ctx.WriteBuffer(result);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(i));
-}
-
-void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(SysPlatformRegion::Global);
-}
-
-void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
- HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h
deleted file mode 100644
index bf652790c..000000000
--- a/src/core/hle/service/am/common_state_getter.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-#include "core/hle/service/am/applet_message_queue.h"
-
-namespace Service::AM {
-
-struct Applet;
-
-class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
-public:
- explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~ICommonStateGetter() override;
-
-private:
- // This is nn::oe::FocusState
- enum class FocusState : u8 {
- InFocus = 1,
- NotInFocus = 2,
- Background = 3,
- };
-
- // This is nn::oe::OperationMode
- enum class OperationMode : u8 {
- Handheld = 0,
- Docked = 1,
- };
-
- // This is nn::am::service::SystemButtonType
- enum class SystemButtonType {
- None,
- HomeButtonShortPressing,
- HomeButtonLongPressing,
- PowerButtonShortPressing,
- PowerButtonLongPressing,
- ShutdownSystem,
- CaptureButtonShortPressing,
- CaptureButtonLongPressing,
- };
-
- enum class SysPlatformRegion : s32 {
- Global = 1,
- Terra = 2,
- };
-
- void GetEventHandle(HLERequestContext& ctx);
- void ReceiveMessage(HLERequestContext& ctx);
- void GetCurrentFocusState(HLERequestContext& ctx);
- void RequestToAcquireSleepLock(HLERequestContext& ctx);
- void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
- void GetReaderLockAccessorEx(HLERequestContext& ctx);
- void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
- void GetOperationMode(HLERequestContext& ctx);
- void GetPerformanceMode(HLERequestContext& ctx);
- void GetBootMode(HLERequestContext& ctx);
- void IsVrModeEnabled(HLERequestContext& ctx);
- void SetVrModeEnabled(HLERequestContext& ctx);
- void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
- void BeginVrModeEx(HLERequestContext& ctx);
- void EndVrModeEx(HLERequestContext& ctx);
- void GetDefaultDisplayResolution(HLERequestContext& ctx);
- void SetCpuBoostMode(HLERequestContext& ctx);
- void GetBuiltInDisplayType(HLERequestContext& ctx);
- void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
- void GetAppletLaunchedHistory(HLERequestContext& ctx);
- void GetSettingsPlatformRegion(HLERequestContext& ctx);
- void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp
deleted file mode 100644
index f80b970f2..000000000
--- a/src/core/hle/service/am/debug_functions.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/debug_functions.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IDebugFunctions::IDebugFunctions(Core::System& system_)
- : ServiceFramework{system_, "IDebugFunctions"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
- {1, nullptr, "OpenMainApplication"},
- {10, nullptr, "PerformSystemButtonPressing"},
- {20, nullptr, "InvalidateTransitionLayer"},
- {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
- {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
- {40, nullptr, "GetAppletResourceUsageInfo"},
- {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
- {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
- {100, nullptr, "SetCpuBoostModeForApplet"},
- {101, nullptr, "CancelCpuBoostModeForApplet"},
- {110, nullptr, "PushToAppletBoundChannelForDebug"},
- {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
- {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
- {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
- {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
- {130, nullptr, "FriendInvitationSetApplicationParameter"},
- {131, nullptr, "FriendInvitationClearApplicationParameter"},
- {132, nullptr, "FriendInvitationPushApplicationParameter"},
- {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
- {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
- {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
- {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDebugFunctions::~IDebugFunctions() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp
deleted file mode 100644
index 4d6858348..000000000
--- a/src/core/hle/service/am/display_controller.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet.h"
-#include "core/hle/service/am/display_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-namespace {
-struct OutputParameters {
- bool was_written;
- s32 fbshare_layer_index;
-};
-
-static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size");
-} // namespace
-
-IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetLastForegroundCaptureImage"},
- {1, nullptr, "UpdateLastForegroundCaptureImage"},
- {2, nullptr, "GetLastApplicationCaptureImage"},
- {3, nullptr, "GetCallerAppletCaptureImage"},
- {4, nullptr, "UpdateCallerAppletCaptureImage"},
- {5, nullptr, "GetLastForegroundCaptureImageEx"},
- {6, nullptr, "GetLastApplicationCaptureImageEx"},
- {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
- {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
- {9, nullptr, "CopyBetweenCaptureBuffers"},
- {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
- {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
- {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
- {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
- {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
- {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
- {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
- {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
- {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
- {20, nullptr, "ClearCaptureBuffer"},
- {21, nullptr, "ClearAppletTransitionBuffer"},
- {22, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"},
- {23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "ReleaseLastApplicationCaptureSharedBuffer"},
- {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
- {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
- {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
- {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
- {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDisplayController::~IDisplayController() = default;
-
-void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- OutputParameters params{};
- const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
- &params.was_written, &params.fbshare_layer_index);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw(params);
-}
-
-void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- OutputParameters params{};
- const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
- &params.was_written, &params.fbshare_layer_index);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw(params);
-}
-
-void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- OutputParameters params{};
- const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
- &params.was_written, &params.fbshare_layer_index);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw(params);
-}
-
-void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- OutputParameters params{};
- const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
- &params.was_written, &params.fbshare_layer_index);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw(params);
-}
-
-void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h
deleted file mode 100644
index 75172580c..000000000
--- a/src/core/hle/service/am/display_controller.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class IDisplayController final : public ServiceFramework<IDisplayController> {
-public:
- explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~IDisplayController() override;
-
-private:
- void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
- void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
- void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
- void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
- void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
- void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
- void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
- void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
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_cabinet.cpp b/src/core/hle/service/am/frontend/applet_cabinet.cpp
index 0862c81b6..4cbc80d63 100644
--- a/src/core/hle/service/am/frontend/applet_cabinet.cpp
+++ b/src/core/hle/service/am/frontend/applet_cabinet.cpp
@@ -9,7 +9,7 @@
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_cabinet.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/nfc/common/device.h"
#include "hid_core/hid_core.h"
diff --git a/src/core/hle/service/am/frontend/applet_controller.cpp b/src/core/hle/service/am/frontend/applet_controller.cpp
index bd3e49fc4..66f52686d 100644
--- a/src/core/hle/service/am/frontend/applet_controller.cpp
+++ b/src/core/hle/service/am/frontend/applet_controller.cpp
@@ -12,7 +12,7 @@
#include "core/hle/result.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_controller.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
diff --git a/src/core/hle/service/am/frontend/applet_error.cpp b/src/core/hle/service/am/frontend/applet_error.cpp
index b97a5f3ea..34ec7013b 100644
--- a/src/core/hle/service/am/frontend/applet_error.cpp
+++ b/src/core/hle/service/am/frontend/applet_error.cpp
@@ -10,7 +10,7 @@
#include "core/frontend/applets/error.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_error.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "core/reporter.h"
namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp
index 3c091a602..d2cabb7b5 100644
--- a/src/core/hle/service/am/frontend/applet_general.cpp
+++ b/src/core/hle/service/am/frontend/applet_general.cpp
@@ -10,7 +10,7 @@
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_data_broker.h"
#include "core/hle/service/am/frontend/applet_general.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "core/reporter.h"
namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/frontend/applet_mii_edit.cpp b/src/core/hle/service/am/frontend/applet_mii_edit.cpp
index e3d19fb3d..0180ab761 100644
--- a/src/core/hle/service/am/frontend/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/frontend/applet_mii_edit.cpp
@@ -7,7 +7,7 @@
#include "core/frontend/applets/mii_edit.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_mii_edit.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/sm/sm.h"
diff --git a/src/core/hle/service/am/frontend/applet_profile_select.cpp b/src/core/hle/service/am/frontend/applet_profile_select.cpp
index efb4053b8..89b5a1eab 100644
--- a/src/core/hle/service/am/frontend/applet_profile_select.cpp
+++ b/src/core/hle/service/am/frontend/applet_profile_select.cpp
@@ -10,7 +10,7 @@
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_profile_select.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
index 034c62f32..d1bc03018 100644
--- a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
@@ -6,7 +6,7 @@
#include "core/frontend/applets/software_keyboard.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
namespace Service::AM::Frontend {
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 6ee4caf34..835c20c4e 100644
--- a/src/core/hle/service/am/frontend/applet_web_browser.cpp
+++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp
@@ -20,9 +20,9 @@
#include "core/hle/result.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/frontend/applet_web_browser.h"
-#include "core/hle/service/am/storage.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/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp
index db2b04575..e662c6cd6 100644
--- a/src/core/hle/service/am/frontend/applets.cpp
+++ b/src/core/hle/service/am/frontend/applets.cpp
@@ -15,11 +15,8 @@
#include "core/frontend/applets/web_browser.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/am/am.h"
-#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_data_broker.h"
#include "core/hle/service/am/applet_manager.h"
-#include "core/hle/service/am/applet_message_queue.h"
-#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/frontend/applet_cabinet.h"
#include "core/hle/service/am/frontend/applet_controller.h"
#include "core/hle/service/am/frontend/applet_error.h"
@@ -29,7 +26,7 @@
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
#include "core/hle/service/am/frontend/applet_web_browser.h"
#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/sm/sm.h"
namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp
deleted file mode 100644
index ed0eb7108..000000000
--- a/src/core/hle/service/am/global_state_controller.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/global_state_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IGlobalStateController::IGlobalStateController(Core::System& system_)
- : ServiceFramework{system_, "IGlobalStateController"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "RequestToEnterSleep"},
- {1, nullptr, "EnterSleep"},
- {2, nullptr, "StartSleepSequence"},
- {3, nullptr, "StartShutdownSequence"},
- {4, nullptr, "StartRebootSequence"},
- {9, nullptr, "IsAutoPowerDownRequested"},
- {10, nullptr, "LoadAndApplyIdlePolicySettings"},
- {11, nullptr, "NotifyCecSettingsChanged"},
- {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
- {13, nullptr, "UpdateDefaultDisplayResolution"},
- {14, nullptr, "ShouldSleepOnBoot"},
- {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
- {30, nullptr, "OpenCradleFirmwareUpdater"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IGlobalStateController::~IGlobalStateController() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h
deleted file mode 100644
index 7125464a1..000000000
--- a/src/core/hle/service/am/global_state_controller.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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::AM {
-
-class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
-public:
- explicit IGlobalStateController(Core::System& system_);
- ~IGlobalStateController() override;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp
deleted file mode 100644
index 640e9fbb7..000000000
--- a/src/core/hle/service/am/home_menu_functions.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/home_menu_functions.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
- : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
- "IHomeMenuFunctions"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
- {11, nullptr, "LockForeground"},
- {12, nullptr, "UnlockForeground"},
- {20, nullptr, "PopFromGeneralChannel"},
- {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
- {30, nullptr, "GetHomeButtonWriterLockAccessor"},
- {31, nullptr, "GetWriterLockAccessorEx"},
- {40, nullptr, "IsSleepEnabled"},
- {41, nullptr, "IsRebootEnabled"},
- {50, nullptr, "LaunchSystemApplet"},
- {51, nullptr, "LaunchStarter"},
- {100, nullptr, "PopRequestLaunchApplicationForDebug"},
- {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
- {200, nullptr, "LaunchDevMenu"},
- {1000, nullptr, "SetLastApplicationExitReason"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- pop_from_general_channel_event =
- service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
-}
-
-IHomeMenuFunctions::~IHomeMenuFunctions() {
- service_context.CloseEvent(pop_from_general_channel_event);
-}
-
-void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h
deleted file mode 100644
index e082d5d73..000000000
--- a/src/core/hle/service/am/home_menu_functions.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
-public:
- explicit IHomeMenuFunctions(Core::System& system_);
- ~IHomeMenuFunctions() override;
-
-private:
- void RequestToGetForeground(HLERequestContext& ctx);
- void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
-
- KernelHelpers::ServiceContext service_context;
-
- Kernel::KEvent* pop_from_general_channel_event;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp
deleted file mode 100644
index 603515284..000000000
--- a/src/core/hle/service/am/idle.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/idle.h"
-
-namespace Service::AM {
-
-IdleSys::IdleSys(Core::System& system_) : ServiceFramework{system_, "idle:sys"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetAutoPowerDownEvent"},
- {1, nullptr, "IsAutoPowerDownRequested"},
- {2, nullptr, "Unknown2"},
- {3, nullptr, "SetHandlingContext"},
- {4, nullptr, "LoadAndApplySettings"},
- {5, nullptr, "ReportUserIsActive"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IdleSys::~IdleSys() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h
deleted file mode 100644
index 15b31f67e..000000000
--- a/src/core/hle/service/am/idle.h
+++ /dev/null
@@ -1,20 +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::AM {
-
-class IdleSys final : public ServiceFramework<IdleSys> {
-public:
- explicit IdleSys(Core::System& system_);
- ~IdleSys() override;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp
deleted file mode 100644
index 6b20814f8..000000000
--- a/src/core/hle/service/am/library_applet_accessor.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/scope_exit.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/applet_data_broker.h"
-#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/library_applet_accessor.h"
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
- std::shared_ptr<AppletDataBroker> broker_,
- std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "ILibraryAppletAccessor"}, broker{std::move(broker_)},
- applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
- {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
- {10, &ILibraryAppletAccessor::Start, "Start"},
- {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
- {25, nullptr, "Terminate"},
- {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
- {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
- {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
- {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
- {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
- {102, nullptr, "PushExtraStorage"},
- {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
- {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
- {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
- {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
- {110, nullptr, "NeedsToExitProcess"},
- {120, nullptr, "GetLibraryAppletInfo"},
- {150, nullptr, "RequestForAppletToGetForeground"},
- {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
-
-void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(broker->GetStateChangedEvent().GetHandle());
-}
-
-void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- std::scoped_lock lk{applet->lock};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(broker->IsCompleted());
-}
-
-void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(applet->terminate_result);
-}
-
-void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- applet->process->Run();
- FrontendExecute();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- ASSERT(applet != nullptr);
- applet->message_queue.RequestExit();
- FrontendRequestExit();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- broker->GetInData().Push(rp.PopIpcInterface<IStorage>().lock());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- std::shared_ptr<IStorage> data;
- const auto res = broker->GetOutData().Pop(&data);
-
- if (res.IsSuccess()) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(res);
- rb.PushIpcInterface(std::move(data));
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- broker->GetInteractiveInData().Push(rp.PopIpcInterface<IStorage>().lock());
- FrontendExecuteInteractive();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- std::shared_ptr<IStorage> data;
- const auto res = broker->GetInteractiveOutData().Pop(&data);
-
- if (res.IsSuccess()) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(res);
- rb.PushIpcInterface(std::move(data));
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(broker->GetOutData().GetEvent());
-}
-
-void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(broker->GetInteractiveOutData().GetEvent());
-}
-
-void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
- // actually used anywhere
- constexpr u64 handle = 0xdeadbeef;
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(handle);
-}
-
-void ILibraryAppletAccessor::FrontendExecute() {
- if (applet->frontend) {
- applet->frontend->Initialize();
- applet->frontend->Execute();
- }
-}
-
-void ILibraryAppletAccessor::FrontendExecuteInteractive() {
- if (applet->frontend) {
- applet->frontend->ExecuteInteractive();
- applet->frontend->Execute();
- }
-}
-
-void ILibraryAppletAccessor::FrontendRequestExit() {
- if (applet->frontend) {
- applet->frontend->RequestExit();
- }
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h
deleted file mode 100644
index 8be29e003..000000000
--- a/src/core/hle/service/am/library_applet_accessor.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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::AM {
-
-class AppletDataBroker;
-struct Applet;
-
-class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
-public:
- explicit ILibraryAppletAccessor(Core::System& system_,
- std::shared_ptr<AppletDataBroker> broker_,
- std::shared_ptr<Applet> applet_);
- ~ILibraryAppletAccessor();
-
-protected:
- void GetAppletStateChangedEvent(HLERequestContext& ctx);
- void IsCompleted(HLERequestContext& ctx);
- void GetResult(HLERequestContext& ctx);
- void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx);
- void Start(HLERequestContext& ctx);
- void RequestExit(HLERequestContext& ctx);
- void PushInData(HLERequestContext& ctx);
- void PopOutData(HLERequestContext& ctx);
- void PushInteractiveInData(HLERequestContext& ctx);
- void PopInteractiveOutData(HLERequestContext& ctx);
- void GetPopOutDataEvent(HLERequestContext& ctx);
- void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
- void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
-
- void FrontendExecute();
- void FrontendExecuteInteractive();
- void FrontendRequestExit();
-
- const std::shared_ptr<AppletDataBroker> broker;
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp
deleted file mode 100644
index 00d5a0705..000000000
--- a/src/core/hle/service/am/library_applet_creator.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/settings.h"
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/service/am/applet_data_broker.h"
-#include "core/hle/service/am/applet_manager.h"
-#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/library_applet_accessor.h"
-#include "core/hle/service/am/library_applet_creator.h"
-#include "core/hle/service/am/library_applet_storage.h"
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/sm/sm.h"
-
-namespace Service::AM {
-
-namespace {
-
-bool ShouldCreateGuestApplet(AppletId applet_id) {
-#define X(Name, name) \
- if (applet_id == AppletId::Name && \
- Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \
- return false; \
- }
-
- X(Cabinet, cabinet)
- X(Controller, controller)
- X(DataErase, data_erase)
- X(Error, error)
- X(NetConnect, net_connect)
- X(ProfileSelect, player_select)
- X(SoftwareKeyboard, swkbd)
- X(MiiEdit, mii_edit)
- X(Web, web)
- X(Shop, shop)
- X(PhotoViewer, photo_viewer)
- X(OfflineWeb, offline_web)
- X(LoginShare, login_share)
- X(WebAuth, wifi_web_auth)
- X(MyPage, my_page)
-
-#undef X
-
- return true;
-}
-
-AppletProgramId AppletIdToProgramId(AppletId applet_id) {
- switch (applet_id) {
- case AppletId::OverlayDisplay:
- return AppletProgramId::OverlayDisplay;
- case AppletId::QLaunch:
- return AppletProgramId::QLaunch;
- case AppletId::Starter:
- return AppletProgramId::Starter;
- case AppletId::Auth:
- return AppletProgramId::Auth;
- case AppletId::Cabinet:
- return AppletProgramId::Cabinet;
- case AppletId::Controller:
- return AppletProgramId::Controller;
- case AppletId::DataErase:
- return AppletProgramId::DataErase;
- case AppletId::Error:
- return AppletProgramId::Error;
- case AppletId::NetConnect:
- return AppletProgramId::NetConnect;
- case AppletId::ProfileSelect:
- return AppletProgramId::ProfileSelect;
- case AppletId::SoftwareKeyboard:
- return AppletProgramId::SoftwareKeyboard;
- case AppletId::MiiEdit:
- return AppletProgramId::MiiEdit;
- case AppletId::Web:
- return AppletProgramId::Web;
- case AppletId::Shop:
- return AppletProgramId::Shop;
- case AppletId::PhotoViewer:
- return AppletProgramId::PhotoViewer;
- case AppletId::Settings:
- return AppletProgramId::Settings;
- case AppletId::OfflineWeb:
- return AppletProgramId::OfflineWeb;
- case AppletId::LoginShare:
- return AppletProgramId::LoginShare;
- case AppletId::WebAuth:
- return AppletProgramId::WebAuth;
- case AppletId::MyPage:
- return AppletProgramId::MyPage;
- default:
- return static_cast<AppletProgramId>(0);
- }
-}
-
-std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
- std::shared_ptr<Applet> caller_applet,
- AppletId applet_id,
- LibraryAppletMode mode) {
- const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
- if (program_id == 0) {
- // Unknown applet
- return {};
- }
-
- // TODO: enable other versions of applets
- enum : u8 {
- Firmware1400 = 14,
- Firmware1500 = 15,
- Firmware1600 = 16,
- Firmware1700 = 17,
- };
-
- auto process = std::make_unique<Process>(system);
- if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
- // Couldn't initialize the guest process
- return {};
- }
-
- const auto applet = std::make_shared<Applet>(system, std::move(process));
- applet->program_id = program_id;
- applet->applet_id = applet_id;
- applet->type = AppletType::LibraryApplet;
- applet->library_applet_mode = mode;
-
- // Set focus state
- switch (mode) {
- case LibraryAppletMode::AllForeground:
- case LibraryAppletMode::NoUi:
- case LibraryAppletMode::PartialForeground:
- case LibraryAppletMode::PartialForegroundIndirectDisplay:
- applet->hid_registration.EnableAppletToGetInput(true);
- applet->focus_state = FocusState::InFocus;
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
- break;
- case LibraryAppletMode::AllForegroundInitiallyHidden:
- applet->hid_registration.EnableAppletToGetInput(false);
- applet->focus_state = FocusState::NotInFocus;
- applet->system_buffer_manager.SetWindowVisibility(false);
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground);
- break;
- }
-
- auto broker = std::make_shared<AppletDataBroker>(system);
- applet->caller_applet = caller_applet;
- applet->caller_applet_broker = broker;
-
- system.GetAppletManager().InsertApplet(applet);
-
- return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
-}
-
-std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
- std::shared_ptr<Applet> caller_applet,
- AppletId applet_id,
- LibraryAppletMode mode) {
- const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
-
- auto process = std::make_unique<Process>(system);
- auto applet = std::make_shared<Applet>(system, std::move(process));
- applet->program_id = program_id;
- applet->applet_id = applet_id;
- applet->type = AppletType::LibraryApplet;
- applet->library_applet_mode = mode;
-
- auto storage = std::make_shared<AppletDataBroker>(system);
- applet->caller_applet = caller_applet;
- applet->caller_applet_broker = storage;
- applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
-
- return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
-}
-
-} // namespace
-
-ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} {
- static const FunctionInfo functions[] = {
- {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
- {1, nullptr, "TerminateAllLibraryApplets"},
- {2, nullptr, "AreAnyLibraryAppletsLeft"},
- {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
- {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
- {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
- };
- RegisterHandlers(functions);
-}
-
-ILibraryAppletCreator::~ILibraryAppletCreator() = default;
-
-void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto applet_id = rp.PopRaw<AppletId>();
- const auto applet_mode = rp.PopRaw<LibraryAppletMode>();
-
- LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
- applet_mode);
-
- std::shared_ptr<ILibraryAppletAccessor> library_applet;
- if (ShouldCreateGuestApplet(applet_id)) {
- library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode);
- }
- if (!library_applet) {
- library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode);
- }
- if (!library_applet) {
- LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- // Applet is created, can now be launched.
- applet->library_applet_launchable_event.Signal();
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet);
-}
-
-void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const s64 size{rp.Pop<s64>()};
-
- LOG_DEBUG(Service_AM, "called, size={}", size);
-
- if (size <= 0) {
- LOG_ERROR(Service_AM, "size is less than or equal to 0");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- std::vector<u8> data(size);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorage>(system, AM::CreateStorage(std::move(data)));
-}
-
-void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- struct Parameters {
- bool is_writable;
- s64 size;
- };
-
- const auto params{rp.PopRaw<Parameters>()};
- const auto handle{ctx.GetCopyHandle(0)};
-
- LOG_DEBUG(Service_AM, "called, is_writable={}, size={}, handle={:08X}", params.is_writable,
- params.size, handle);
-
- if (params.size <= 0) {
- LOG_ERROR(Service_AM, "size is less than or equal to 0");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
-
- if (transfer_mem.IsNull()) {
- LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorage>(
- system, AM::CreateTransferMemoryStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(),
- params.is_writable, params.size));
-}
-
-void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const s64 size{rp.Pop<s64>()};
- const auto handle{ctx.GetCopyHandle(0)};
-
- LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
-
- if (size <= 0) {
- LOG_ERROR(Service_AM, "size is less than or equal to 0");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
-
- if (transfer_mem.IsNull()) {
- LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorage>(
- system, AM::CreateHandleStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), size));
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h
deleted file mode 100644
index 551f287bd..000000000
--- a/src/core/hle/service/am/library_applet_creator.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
-public:
- explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~ILibraryAppletCreator() override;
-
-private:
- void CreateLibraryApplet(HLERequestContext& ctx);
- void CreateStorage(HLERequestContext& ctx);
- void CreateTransferMemoryStorage(HLERequestContext& ctx);
- void CreateHandleStorage(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp
deleted file mode 100644
index d6108fba3..000000000
--- a/src/core/hle/service/am/library_applet_proxy.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet_common_functions.h"
-#include "core/hle/service/am/audio_controller.h"
-#include "core/hle/service/am/common_state_getter.h"
-#include "core/hle/service/am/debug_functions.h"
-#include "core/hle/service/am/display_controller.h"
-#include "core/hle/service/am/global_state_controller.h"
-#include "core/hle/service/am/home_menu_functions.h"
-#include "core/hle/service/am/library_applet_creator.h"
-#include "core/hle/service/am/library_applet_proxy.h"
-#include "core/hle/service/am/library_applet_self_accessor.h"
-#include "core/hle/service/am/process_winding_controller.h"
-#include "core/hle/service/am/self_controller.h"
-#include "core/hle/service/am/window_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> applet_, Core::System& system_)
- : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
- applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
- {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
- {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
- {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
- {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
- {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
- {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
- {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
- {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
- {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
- {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
- {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-ILibraryAppletProxy::~ILibraryAppletProxy() = default;
-
-void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ICommonStateGetter>(system, applet);
-}
-
-void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
-}
-
-void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IWindowController>(system, applet);
-}
-
-void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioController>(system);
-}
-
-void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDisplayController>(system, applet);
-}
-
-void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IProcessWindingController>(system, applet);
-}
-
-void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
-}
-
-void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet);
-}
-
-void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
-}
-
-void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHomeMenuFunctions>(system);
-}
-
-void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IGlobalStateController>(system);
-}
-
-void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDebugFunctions>(system);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h
deleted file mode 100644
index 8f7a25897..000000000
--- a/src/core/hle/service/am/library_applet_proxy.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
-public:
- explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> applet_, Core::System& system_);
- ~ILibraryAppletProxy();
-
-private:
- void GetCommonStateGetter(HLERequestContext& ctx);
- void GetSelfController(HLERequestContext& ctx);
- void GetWindowController(HLERequestContext& ctx);
- void GetAudioController(HLERequestContext& ctx);
- void GetDisplayController(HLERequestContext& ctx);
- void GetProcessWindingController(HLERequestContext& ctx);
- void GetLibraryAppletCreator(HLERequestContext& ctx);
- void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx);
- void GetAppletCommonFunctions(HLERequestContext& ctx);
- void GetHomeMenuFunctions(HLERequestContext& ctx);
- void GetGlobalStateController(HLERequestContext& ctx);
- void GetDebugFunctions(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nvnflinger;
- std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp
deleted file mode 100644
index b560f580b..000000000
--- a/src/core/hle/service/am/library_applet_self_accessor.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/scope_exit.h"
-#include "core/core_timing.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/file_sys/registered_cache.h"
-#include "core/hle/service/acc/profile_manager.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/applet_data_broker.h"
-#include "core/hle/service/am/applet_manager.h"
-#include "core/hle/service/am/frontend/applet_cabinet.h"
-#include "core/hle/service/am/frontend/applet_controller.h"
-#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
-#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
-#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/library_applet_self_accessor.h"
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/sm/sm.h"
-#include "hid_core/hid_types.h"
-
-namespace Service::AM {
-
-namespace {
-
-AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) {
- if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) {
- // TODO: is this actually the application ID?
- return {
- .applet_id = caller_applet->applet_id,
- .application_id = caller_applet->program_id,
- };
- } else {
- return {
- .applet_id = AppletId::QLaunch,
- .application_id = 0x0100000000001000ull,
- };
- }
-}
-
-} // namespace
-
-ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
- std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)},
- broker{applet->caller_applet_broker} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
- {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
- {2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"},
- {3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"},
- {5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"},
- {6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"},
- {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
- {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
- {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
- {13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "CanUseApplicationCore"},
- {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
- {15, nullptr, "GetMainAppletApplicationControlProperty"},
- {16, nullptr, "GetMainAppletStorageId"},
- {17, nullptr, "GetCallerAppletIdentityInfoStack"},
- {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
- {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
- {20, nullptr, "PopExtraStorage"},
- {25, nullptr, "GetPopExtraStorageEvent"},
- {30, nullptr, "UnpopInData"},
- {31, nullptr, "UnpopExtraStorage"},
- {40, nullptr, "GetIndirectLayerProducerHandle"},
- {50, nullptr, "ReportVisibleError"},
- {51, nullptr, "ReportVisibleErrorWithErrorContext"},
- {60, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"},
- {70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "GetCurrentApplicationId"},
- {80, nullptr, "RequestExitToSelf"},
- {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
- {100, nullptr, "CreateGameMovieTrimmer"},
- {101, nullptr, "ReserveResourceForMovieOperation"},
- {102, nullptr, "UnreserveResourceForMovieOperation"},
- {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
- {120, nullptr, "GetLaunchStorageInfoForDebug"},
- {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
- {140, nullptr, "SetApplicationMemoryReservation"},
- {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
- {160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"},
- };
- // clang-format on
- RegisterHandlers(functions);
-}
-
-ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
-
-void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- std::shared_ptr<IStorage> data;
- const auto res = broker->GetInData().Pop(&data);
-
- if (res.IsSuccess()) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(res);
- rb.PushIpcInterface(std::move(data));
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- broker->GetOutData().Push(rp.PopIpcInterface<IStorage>().lock());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- std::shared_ptr<IStorage> data;
- const auto res = broker->GetInteractiveInData().Pop(&data);
-
- if (res.IsSuccess()) {
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(res);
- rb.PushIpcInterface(std::move(data));
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- broker->GetInteractiveOutData().Push(rp.PopIpcInterface<IStorage>().lock());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(broker->GetInData().GetEvent());
-}
-
-void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(broker->GetInteractiveInData().GetEvent());
-}
-
-void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid);
- broker->SignalCompletion();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
- struct LibraryAppletInfo {
- AppletId applet_id;
- LibraryAppletMode library_applet_mode;
- };
-
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- const LibraryAppletInfo applet_info{
- .applet_id = applet->applet_id,
- .library_applet_mode = applet->library_applet_mode,
- };
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushRaw(applet_info);
-}
-
-void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- const AppletIdentityInfo applet_info{
- .applet_id = AppletId::QLaunch,
- .application_id = 0x0100000000001000ull,
- };
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(applet_info);
-}
-
-void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- // TODO: This appears to read the NPDM from state and check the core mask of the applet.
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(0);
-}
-
-void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(GetCallerIdentity(applet));
-}
-
-void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(0);
-}
-
-void ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) {
- // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
- auto identity = GetCallerIdentity(applet);
-
- // TODO(bunnei): This should be configurable
- LOG_DEBUG(Service_AM, "called");
-
- // Get supported languages from NACP, if possible
- // Default to 0 (all languages supported)
- u32 supported_languages = 0;
-
- const auto res = [this, identity] {
- const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
- system.GetContentProvider()};
- auto metadata = pm.GetControlMetadata();
- if (metadata.first != nullptr) {
- return metadata;
- }
-
- const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
- system.GetFileSystemController(),
- system.GetContentProvider()};
- return pm_update.GetControlMetadata();
- }();
-
- if (res.first != nullptr) {
- supported_languages = res.first->GetSupportedLanguages();
- }
-
- // Call IApplicationManagerInterface implementation.
- auto& service_manager = system.ServiceManager();
- auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
-
- // Get desired application language
- u8 desired_language{};
- const auto res_lang =
- app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
- if (res_lang != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res_lang);
- return;
- }
-
- // Convert to settings language code.
- u64 language_code{};
- const auto res_code =
- app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
- if (res_code != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res_code);
- return;
- }
-
- LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(language_code);
-}
-
-void ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- u64 application_id = 0;
- if (auto caller_applet = applet->caller_applet.lock(); caller_applet) {
- application_id = caller_applet->program_id;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(application_id);
-}
-
-void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
- const Service::Account::ProfileManager manager{};
- bool is_empty{true};
- s32 user_count{-1};
-
- LOG_INFO(Service_AM, "called");
-
- if (manager.GetUserCount() > 0) {
- is_empty = false;
- user_count = static_cast<s32>(manager.GetUserCount());
- ctx.WriteBuffer(manager.GetAllUsers());
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_empty);
- rb.Push(user_count);
-}
-
-void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(0);
-}
-
-void ILibraryAppletSelfAccessor::Cmd160(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(0);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h
deleted file mode 100644
index 8717a989a..000000000
--- a/src/core/hle/service/am/library_applet_self_accessor.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <deque>
-#include <vector>
-
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-class AppletDataBroker;
-struct Applet;
-
-class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
-public:
- explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~ILibraryAppletSelfAccessor() override;
-
-private:
- void PopInData(HLERequestContext& ctx);
- void PushOutData(HLERequestContext& ctx);
- void PopInteractiveInData(HLERequestContext& ctx);
- void PushInteractiveOutData(HLERequestContext& ctx);
- void GetPopInDataEvent(HLERequestContext& ctx);
- void GetPopInteractiveInDataEvent(HLERequestContext& ctx);
- void GetLibraryAppletInfo(HLERequestContext& ctx);
- void GetMainAppletIdentityInfo(HLERequestContext& ctx);
- void CanUseApplicationCore(HLERequestContext& ctx);
- void ExitProcessAndReturn(HLERequestContext& ctx);
- void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
- void GetDesirableKeyboardLayout(HLERequestContext& ctx);
- void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx);
- void GetCurrentApplicationId(HLERequestContext& ctx);
- void GetMainAppletAvailableUsers(HLERequestContext& ctx);
- void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
- void Cmd160(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
- const std::shared_ptr<AppletDataBroker> broker;
-};
-
-} // namespace Service::AM
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/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp
deleted file mode 100644
index d0bd8d95e..000000000
--- a/src/core/hle/service/am/lock_accessor.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/lock_accessor.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-ILockAccessor::ILockAccessor(Core::System& system_)
- : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1, &ILockAccessor::TryLock, "TryLock"},
- {2, &ILockAccessor::Unlock, "Unlock"},
- {3, &ILockAccessor::GetEvent, "GetEvent"},
- {4,&ILockAccessor::IsLocked, "IsLocked"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
-}
-
-ILockAccessor::~ILockAccessor() {
- service_context.CloseEvent(lock_event);
-};
-
-void ILockAccessor::TryLock(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto return_handle = rp.Pop<bool>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
-
- // TODO: When return_handle is true this function should return the lock handle
-
- is_locked = true;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_locked);
-}
-
-void ILockAccessor::Unlock(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- is_locked = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ILockAccessor::GetEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- lock_event->Signal();
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(lock_event->GetReadableEvent());
-}
-
-void ILockAccessor::IsLocked(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_locked);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h
deleted file mode 100644
index 626f60e07..000000000
--- a/src/core/hle/service/am/lock_accessor.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-class ILockAccessor final : public ServiceFramework<ILockAccessor> {
-public:
- explicit ILockAccessor(Core::System& system_);
- ~ILockAccessor() override;
-
-private:
- void TryLock(HLERequestContext& ctx);
- void Unlock(HLERequestContext& ctx);
- void GetEvent(HLERequestContext& ctx);
- void IsLocked(HLERequestContext& ctx);
-
- bool is_locked{};
-
- Kernel::KEvent* lock_event;
- KernelHelpers::ServiceContext service_context;
-};
-
-} // namespace Service::AM
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/omm.cpp b/src/core/hle/service/am/omm.cpp
deleted file mode 100644
index 66824e495..000000000
--- a/src/core/hle/service/am/omm.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/omm.h"
-
-namespace Service::AM {
-
-OMM::OMM(Core::System& system_) : ServiceFramework{system_, "omm"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetOperationMode"},
- {1, nullptr, "GetOperationModeChangeEvent"},
- {2, nullptr, "EnableAudioVisual"},
- {3, nullptr, "DisableAudioVisual"},
- {4, nullptr, "EnterSleepAndWait"},
- {5, nullptr, "GetCradleStatus"},
- {6, nullptr, "FadeInDisplay"},
- {7, nullptr, "FadeOutDisplay"},
- {8, nullptr, "GetCradleFwVersion"},
- {9, nullptr, "NotifyCecSettingsChanged"},
- {10, nullptr, "SetOperationModePolicy"},
- {11, nullptr, "GetDefaultDisplayResolution"},
- {12, nullptr, "GetDefaultDisplayResolutionChangeEvent"},
- {13, nullptr, "UpdateDefaultDisplayResolution"},
- {14, nullptr, "ShouldSleepOnBoot"},
- {15, nullptr, "NotifyHdcpApplicationExecutionStarted"},
- {16, nullptr, "NotifyHdcpApplicationExecutionFinished"},
- {17, nullptr, "NotifyHdcpApplicationDrawingStarted"},
- {18, nullptr, "NotifyHdcpApplicationDrawingFinished"},
- {19, nullptr, "GetHdcpAuthenticationFailedEvent"},
- {20, nullptr, "GetHdcpAuthenticationFailedEmulationEnabled"},
- {21, nullptr, "SetHdcpAuthenticationFailedEmulation"},
- {22, nullptr, "GetHdcpStateChangeEvent"},
- {23, nullptr, "GetHdcpState"},
- {24, nullptr, "ShowCardUpdateProcessing"},
- {25, nullptr, "SetApplicationCecSettingsAndNotifyChanged"},
- {26, nullptr, "GetOperationModeSystemInfo"},
- {27, nullptr, "GetAppletFullAwakingSystemEvent"},
- {28, nullptr, "CreateCradleFirmwareUpdater"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-OMM::~OMM() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h
deleted file mode 100644
index 73d0c82d5..000000000
--- a/src/core/hle/service/am/omm.h
+++ /dev/null
@@ -1,20 +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::AM {
-
-class OMM final : public ServiceFramework<OMM> {
-public:
- explicit OMM(Core::System& system_);
- ~OMM() override;
-};
-
-} // 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/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp
deleted file mode 100644
index b48b52797..000000000
--- a/src/core/hle/service/am/process_winding_controller.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/library_applet_accessor.h"
-#include "core/hle/service/am/process_winding_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IProcessWindingController::IProcessWindingController(Core::System& system_,
- std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
- {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
- {21, nullptr, "PushContext"},
- {22, nullptr, "PopContext"},
- {23, nullptr, "CancelWindingReservation"},
- {30, nullptr, "WindAndDoReserved"},
- {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
- {41, nullptr, "ReserveToStartAndWait"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IProcessWindingController::~IProcessWindingController() = default;
-
-void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(applet->launch_reason);
-}
-
-void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
- const auto caller_applet = applet->caller_applet.lock();
- if (caller_applet == nullptr) {
- LOG_ERROR(Service_AM, "No calling applet available");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_broker,
- caller_applet);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h
deleted file mode 100644
index 71ae4c4f5..000000000
--- a/src/core/hle/service/am/process_winding_controller.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
-public:
- explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~IProcessWindingController() override;
-
-private:
- void GetLaunchReason(HLERequestContext& ctx);
- void OpenCallingLibraryApplet(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp
deleted file mode 100644
index 65e249c0c..000000000
--- a/src/core/hle/service/am/self_controller.cpp
+++ /dev/null
@@ -1,470 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/result.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/frontend/applets.h"
-#include "core/hle/service/am/self_controller.h"
-#include "core/hle/service/caps/caps_su.h"
-#include "core/hle/service/hle_ipc.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/sm/sm.h"
-#include "core/hle/service/vi/vi_results.h"
-
-namespace Service::AM {
-
-ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
- Nvnflinger::Nvnflinger& nvnflinger_)
- : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move(
- applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ISelfController::Exit, "Exit"},
- {1, &ISelfController::LockExit, "LockExit"},
- {2, &ISelfController::UnlockExit, "UnlockExit"},
- {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
- {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
- {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
- {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
- {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
- {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
- {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
- {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
- {15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"},
- {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
- {17, nullptr, "SetControllerFirmwareUpdateSection"},
- {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
- {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
- {20, nullptr, "SetDesirableKeyboardLayout"},
- {21, nullptr, "GetScreenShotProgramId"},
- {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
- {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
- {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
- {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
- {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
- {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
- {46, nullptr, "SetRecordingLayerCompositionEnabled"},
- {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
- {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
- {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
- {61, &ISelfController::SetMediaPlaybackState, "SetMediaPlaybackState"},
- {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
- {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
- {64, nullptr, "SetInputDetectionSourceSet"},
- {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
- {66, nullptr, "GetCurrentIlluminance"},
- {67, nullptr, "IsIlluminanceAvailable"},
- {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
- {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
- {70, nullptr, "ReportMultimediaError"},
- {71, nullptr, "GetCurrentIlluminanceEx"},
- {72, nullptr, "SetInputDetectionPolicy"},
- {80, nullptr, "SetWirelessPriorityMode"},
- {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
- {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
- {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
- {110, nullptr, "SetApplicationAlbumUserData"},
- {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
- {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
- {1000, nullptr, "GetDebugStorageChannel"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-ISelfController::~ISelfController() = default;
-
-void ISelfController::Exit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-
- // TODO
- system.Exit();
-}
-
-void ISelfController::LockExit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- system.SetExitLocked(true);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::UnlockExit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- system.SetExitLocked(false);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-
- if (system.GetExitRequested()) {
- system.Exit();
- }
-}
-
-void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
-
- std::scoped_lock lk{applet->lock};
- applet->fatal_section_count++;
- LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called.");
-
- // Entry and exit of fatal sections must be balanced.
- std::scoped_lock lk{applet->lock};
- if (applet->fatal_section_count == 0) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultFatalSectionCountImbalance);
- return;
- }
-
- applet->fatal_section_count--;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- applet->library_applet_launchable_event.Signal();
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle());
-}
-
-void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto permission = rp.PopEnum<ScreenshotPermission>();
- LOG_DEBUG(Service_AM, "called, permission={}", permission);
-
- std::scoped_lock lk{applet->lock};
- applet->screenshot_permission = permission;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const bool notification_enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
-
- std::scoped_lock lk{applet->lock};
- applet->operation_mode_changed_notification_enabled = notification_enabled;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const bool notification_enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
-
- std::scoped_lock lk{applet->lock};
- applet->performance_mode_changed_notification_enabled = notification_enabled;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto flags = rp.PopRaw<FocusHandlingMode>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
- flags.unknown0, flags.unknown1, flags.unknown2);
-
- std::scoped_lock lk{applet->lock};
- applet->focus_handling_mode = flags;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
- applet->restart_message_enabled = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
- std::scoped_lock lk{applet->lock};
- applet->screen_shot_identity = rp.PopRaw<AppletIdentityInfo>();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const bool enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
-
- std::scoped_lock lk{applet->lock};
- ASSERT(applet->type == AppletType::Application);
- applet->out_of_focus_suspension_enabled = enabled;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>();
- LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation));
-
- std::scoped_lock lk{applet->lock};
- applet->album_image_orientation = orientation;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- u64 layer_id{};
- applet->managed_layer_holder.Initialize(&nvnflinger);
- applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(layer_id);
-}
-
-void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
-}
-
-void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- u64 buffer_id, layer_id;
- applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
- rb.Push<s64>(buffer_id);
- rb.Push<s64>(layer_id);
-}
-
-void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- u64 buffer_id, layer_id;
- applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
- rb.Push<s64>(buffer_id);
-}
-
-Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
- if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id,
- applet->library_applet_mode)) {
- return ResultSuccess;
- }
-
- return VI::ResultOperationFailed;
-}
-
-void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- u64 layer_id{};
- u64 recording_layer_id{};
- applet->managed_layer_holder.Initialize(&nvnflinger);
- applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(layer_id);
- rb.Push(recording_layer_id);
-}
-
-void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetMediaPlaybackState(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u8 state = rp.Pop<u8>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
- LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension);
-
- std::scoped_lock lk{applet->lock};
- applet->idle_time_detection_extension = extension;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- std::scoped_lock lk{applet->lock};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension);
-}
-
-void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- std::scoped_lock lk{applet->lock};
- applet->auto_sleep_disabled = rp.Pop<bool>();
-
- // On the system itself, if the previous state of is_auto_sleep_disabled
- // differed from the current value passed in, it'd signify the internal
- // window manager to update (and also increment some statistics like update counts)
- //
- // It'd also indicate this change to an idle handling context.
- //
- // However, given we're emulating this behavior, most of this can be ignored
- // and it's sufficient to simply set the member variable for querying via
- // IsAutoSleepDisabled().
-
- LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called.");
-
- std::scoped_lock lk{applet->lock};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(applet->auto_sleep_disabled);
-}
-
-void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called.");
-
- std::scoped_lock lk{applet->lock};
- // This command returns the total number of system ticks since ISelfController creation
- // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
- // can just always return 0 ticks.
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(applet->suspended_ticks);
-}
-
-void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called.");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle());
-}
-
-void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- // This service call sets an internal flag whether a notification is shown when an image is
- // captured. Currently we do not support capturing images via the capture button, so this can be
- // stubbed for now.
- const bool enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
-
- std::scoped_lock lk{applet->lock};
- applet->album_image_taken_notification_enabled = enabled;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
-
- LOG_INFO(Service_AM, "called, report_option={}", report_option);
-
- const auto screenshot_service =
- system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
- "caps:su");
-
- if (screenshot_service) {
- screenshot_service->CaptureAndSaveScreenshot(report_option);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto enabled = rp.Pop<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
-
- std::scoped_lock lk{applet->lock};
- applet->record_volume_muted = enabled;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h
deleted file mode 100644
index ab21a1881..000000000
--- a/src/core/hle/service/am/self_controller.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/hle_ipc.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-struct Applet;
-
-class ISelfController final : public ServiceFramework<ISelfController> {
-public:
- explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
- Nvnflinger::Nvnflinger& nvnflinger_);
- ~ISelfController() override;
-
-private:
- void Exit(HLERequestContext& ctx);
- void LockExit(HLERequestContext& ctx);
- void UnlockExit(HLERequestContext& ctx);
- void EnterFatalSection(HLERequestContext& ctx);
- void LeaveFatalSection(HLERequestContext& ctx);
- void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
- void SetScreenShotPermission(HLERequestContext& ctx);
- void SetOperationModeChangedNotification(HLERequestContext& ctx);
- void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
- void SetFocusHandlingMode(HLERequestContext& ctx);
- void SetRestartMessageEnabled(HLERequestContext& ctx);
- void SetScreenShotAppletIdentityInfo(HLERequestContext& ctx);
- void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
- void SetAlbumImageOrientation(HLERequestContext& ctx);
- void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
- void GetSystemSharedBufferHandle(HLERequestContext& ctx);
- void GetSystemSharedLayerHandle(HLERequestContext& ctx);
- void CreateManagedDisplayLayer(HLERequestContext& ctx);
- void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
- void SetHandlesRequestToDisplay(HLERequestContext& ctx);
- void ApproveToDisplay(HLERequestContext& ctx);
- void SetMediaPlaybackState(HLERequestContext& ctx);
- void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
- void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
- void ReportUserIsActive(HLERequestContext& ctx);
- void SetAutoSleepDisabled(HLERequestContext& ctx);
- void IsAutoSleepDisabled(HLERequestContext& ctx);
- void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
- void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
- void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
- void SaveCurrentScreenshot(HLERequestContext& ctx);
- void SetRecordVolumeMuted(HLERequestContext& ctx);
-
- Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
-
- Nvnflinger::Nvnflinger& nvnflinger;
- const std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
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
new file mode 100644
index 000000000..21747783a
--- /dev/null
+++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
+#include "core/hle/service/am/service/library_applet_proxy.h"
+#include "core/hle/service/am/service/system_applet_proxy.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_)
+ : ServiceFramework{system_, "appletAE"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
+ {200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
+ {201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
+ {300, nullptr, "OpenOverlayAppletProxy"},
+ {350, nullptr, "OpenSystemApplicationProxy"},
+ {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
+ {410, nullptr, "GetSystemAppletControllerForDebug"},
+ {1000, nullptr, "GetDebugFunctions"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAllSystemAppletProxiesService::~IAllSystemAppletProxiesService() = default;
+
+Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
+ Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle) {
+ 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());
+ R_SUCCEED();
+ } else {
+ UNIMPLEMENTED();
+ R_THROW(ResultUnknown);
+ }
+}
+
+Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
+ Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
+ 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());
+ R_SUCCEED();
+ } else {
+ UNIMPLEMENTED();
+ R_THROW(ResultUnknown);
+ }
+}
+
+Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
+ Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle) {
+ LOG_DEBUG(Service_AM, "called");
+
+ AppletAttribute attribute{};
+ R_RETURN(
+ this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));
+}
+
+std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
+ ProcessId process_id) {
+ return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
+}
+
+} // namespace Service::AM
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
new file mode 100644
index 000000000..0e2dcb86d
--- /dev/null
+++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h
@@ -0,0 +1,41 @@
+// 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"
+
+namespace Service {
+
+namespace AM {
+
+struct Applet;
+struct AppletAttribute;
+class ILibraryAppletProxy;
+class ISystemAppletProxy;
+
+class IAllSystemAppletProxiesService final
+ : public ServiceFramework<IAllSystemAppletProxiesService> {
+public:
+ explicit IAllSystemAppletProxiesService(Core::System& system_);
+ ~IAllSystemAppletProxiesService() override;
+
+private:
+ Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy,
+ ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle);
+ Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy,
+ ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
+ Result OpenLibraryAppletProxyOld(
+ Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle);
+
+private:
+ std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/service/applet_common_functions.cpp b/src/core/hle/service/am/service/applet_common_functions.cpp
new file mode 100644
index 000000000..0f29ab285
--- /dev/null
+++ b/src/core/hle/service/am/service/applet_common_functions.cpp
@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/service/applet_common_functions.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
+ std::shared_ptr<Applet> applet_)
+ : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "SetTerminateResult"},
+ {10, nullptr, "ReadThemeStorage"},
+ {11, nullptr, "WriteThemeStorage"},
+ {20, nullptr, "PushToAppletBoundChannel"},
+ {21, nullptr, "TryPopFromAppletBoundChannel"},
+ {40, nullptr, "GetDisplayLogicalResolution"},
+ {42, nullptr, "SetDisplayMagnification"},
+ {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
+ {51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
+ {52, nullptr, "IsHomeButtonShortPressedBlocked"},
+ {60, nullptr, "IsVrModeCurtainRequired"},
+ {61, nullptr, "IsSleepRequiredByHighTemperature"},
+ {62, nullptr, "IsSleepRequiredByLowBattery"},
+ {70, D<&IAppletCommonFunctions::SetCpuBoostRequestPriority>, "SetCpuBoostRequestPriority"},
+ {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
+ {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
+ {90, nullptr, "OpenNamedChannelAsParent"},
+ {91, nullptr, "OpenNamedChannelAsChild"},
+ {100, nullptr, "SetApplicationCoreUsageMode"},
+ {300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAppletCommonFunctions::~IAppletCommonFunctions() = default;
+
+Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
+ Out<bool> out_home_button_double_click_enabled) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_home_button_double_click_enabled = false;
+ R_SUCCEED();
+}
+
+Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ std::scoped_lock lk{applet->lock};
+ applet->cpu_boost_request_priority = priority;
+ R_SUCCEED();
+}
+
+Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_application_id = system.GetApplicationProcessProgramID() & ~0xFFFULL;
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/applet_common_functions.h b/src/core/hle/service/am/service/applet_common_functions.h
new file mode 100644
index 000000000..4424fc83d
--- /dev/null
+++ b/src/core/hle/service/am/service/applet_common_functions.h
@@ -0,0 +1,26 @@
+// 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::AM {
+
+struct Applet;
+
+class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
+public:
+ explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
+ ~IAppletCommonFunctions() override;
+
+private:
+ Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
+ Result SetCpuBoostRequestPriority(s32 priority);
+ Result GetCurrentApplicationId(Out<u64> out_application_id);
+
+ const std::shared_ptr<Applet> applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp
new file mode 100644
index 000000000..6e7d110e8
--- /dev/null
+++ b/src/core/hle/service/am/service/application_accessor.cpp
@@ -0,0 +1,138 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/result.h"
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/applet_data_broker.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/application_accessor.h"
+#include "core/hle/service/am/service/library_applet_accessor.h"
+#include "core/hle/service/am/service/storage.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
+ {1, nullptr, "IsCompleted"},
+ {10, D<&IApplicationAccessor::Start>, "Start"},
+ {20, D<&IApplicationAccessor::RequestExit>, "RequestExit"},
+ {25, D<&IApplicationAccessor::Terminate>, "Terminate"},
+ {30, D<&IApplicationAccessor::GetResult>, "GetResult"},
+ {101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"},
+ {110, nullptr, "TerminateAllLibraryApplets"},
+ {111, nullptr, "AreAnyLibraryAppletsLeft"},
+ {112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"},
+ {120, nullptr, "GetApplicationId"},
+ {121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"},
+ {122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"},
+ {123, nullptr, "GetApplicationLaunchProperty"},
+ {124, nullptr, "GetApplicationLaunchRequestInfo"},
+ {130, D<&IApplicationAccessor::SetUsers>, "SetUsers"},
+ {131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"},
+ {132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"},
+ {140, nullptr, "GetDesirableUids"},
+ {150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"},
+ {160, nullptr, "SetApplicationAttribute"},
+ {170, nullptr, "HasSaveDataAccessPermission"},
+ {180, nullptr, "PushToFriendInvitationStorageChannel"},
+ {190, nullptr, "PushToNotificationStorageChannel"},
+ {200, nullptr, "RequestApplicationSoftReset"},
+ {201, nullptr, "RestartApplicationTimer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationAccessor::~IApplicationAccessor() = default;
+
+Result IApplicationAccessor::Start() {
+ LOG_INFO(Service_AM, "called");
+ m_applet->process->Run();
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::RequestExit() {
+ LOG_INFO(Service_AM, "called");
+ m_applet->message_queue.RequestExit();
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::Terminate() {
+ LOG_INFO(Service_AM, "called");
+ m_applet->process->Terminate();
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::GetResult() {
+ LOG_INFO(Service_AM, "called");
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::GetAppletStateChangedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_AM, "called");
+ *out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind,
+ SharedPointer<IStorage> storage) {
+ LOG_INFO(Service_AM, "called, kind={}", kind);
+
+ switch (kind) {
+ case LaunchParameterKind::AccountPreselectedUser:
+ m_applet->preselected_user_launch_parameter.push_back(storage->GetData());
+ R_SUCCEED();
+ default:
+ R_THROW(ResultUnknown);
+ }
+}
+
+Result IApplicationAccessor::GetApplicationControlProperty(
+ OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_THROW(ResultUnknown);
+}
+
+Result IApplicationAccessor::SetUsers(bool enable,
+ InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids) {
+ LOG_INFO(Service_AM, "called, enable={} user_id_count={}", enable, user_ids.size());
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::GetCurrentLibraryApplet(
+ Out<SharedPointer<ILibraryAppletAccessor>> out_accessor) {
+ LOG_INFO(Service_AM, "(STUBBED) called");
+ *out_accessor = nullptr;
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::RequestForApplicationToGetForeground() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_THROW(ResultUnknown);
+}
+
+Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_is_available = true;
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::GetNsRightsEnvironmentHandle(Out<u64> out_handle) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_handle = 0xdeadbeef;
+ R_SUCCEED();
+}
+
+Result IApplicationAccessor::ReportApplicationExitTimeout() {
+ LOG_ERROR(Service_AM, "called");
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_accessor.h b/src/core/hle/service/am/service/application_accessor.h
new file mode 100644
index 000000000..39a9b2153
--- /dev/null
+++ b/src/core/hle/service/am/service/application_accessor.h
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/uuid.h"
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+struct Applet;
+class ILibraryAppletAccessor;
+class IStorage;
+
+class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
+public:
+ explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~IApplicationAccessor() override;
+
+private:
+ Result Start();
+ Result RequestExit();
+ Result Terminate();
+ Result GetResult();
+ Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result PushLaunchParameter(LaunchParameterKind kind, SharedPointer<IStorage> storage);
+ Result GetApplicationControlProperty(OutBuffer<BufferAttr_HipcMapAlias> out_control_property);
+ Result SetUsers(bool enable, InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids);
+ Result GetCurrentLibraryApplet(Out<SharedPointer<ILibraryAppletAccessor>> out_accessor);
+ Result RequestForApplicationToGetForeground();
+ Result CheckRightsEnvironmentAvailable(Out<bool> out_is_available);
+ Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
+ Result ReportApplicationExitTimeout();
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp
new file mode 100644
index 000000000..568bb0122
--- /dev/null
+++ b/src/core/hle/service/am/service/application_creator.cpp
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/application_accessor.h"
+#include "core/hle/service/am/service/application_creator.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IApplicationCreator::IApplicationCreator(Core::System& system_)
+ : ServiceFramework{system_, "IApplicationCreator"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
+ {1, nullptr, "PopLaunchRequestedApplication"},
+ {10, nullptr, "CreateSystemApplication"},
+ {100, nullptr, "PopFloatingApplicationForDevelopment"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationCreator::~IApplicationCreator() = default;
+
+Result IApplicationCreator::CreateApplication(
+ Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
+ LOG_ERROR(Service_NS, "called, application_id={:x}", application_id);
+ R_THROW(ResultUnknown);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_creator.h b/src/core/hle/service/am/service/application_creator.h
new file mode 100644
index 000000000..9f939ebf6
--- /dev/null
+++ b/src/core/hle/service/am/service/application_creator.h
@@ -0,0 +1,23 @@
+// 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::AM {
+
+class IApplicationAccessor;
+struct Applet;
+
+class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
+public:
+ explicit IApplicationCreator(Core::System& system_);
+ ~IApplicationCreator() override;
+
+private:
+ Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp
new file mode 100644
index 000000000..cb53b07e0
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.cpp
@@ -0,0 +1,485 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "common/uuid.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/savedata_factory.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/service/application_functions.h"
+#include "core/hle/service/am/service/storage.h"
+#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/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 {
+
+IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
+ {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
+ {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
+ {12, nullptr, "CreateApplicationAndRequestToStart"},
+ {13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
+ {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
+ {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
+ {20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
+ {21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
+ {22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
+ {23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
+ {24, nullptr, "GetLaunchStorageInfoForDebug"},
+ {25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
+ {26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
+ {27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
+ {28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
+ {29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"},
+ {30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
+ {31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
+ {32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
+ {33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
+ {34, nullptr, "SelectApplicationLicense"},
+ {35, nullptr, "GetDeviceSaveDataSizeMax"},
+ {36, nullptr, "GetLimitedApplicationLicense"},
+ {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
+ {40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
+ {50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
+ {60, nullptr, "SetMediaPlaybackStateForApplication"},
+ {65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
+ {66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
+ {67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
+ {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
+ {70, nullptr, "RequestToShutdown"},
+ {71, nullptr, "RequestToReboot"},
+ {72, nullptr, "RequestToSleep"},
+ {80, nullptr, "ExitAndRequestToShowThanksMessage"},
+ {90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
+ {100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
+ {101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
+ {102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
+ {110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
+ {111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
+ {120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
+ {121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
+ {122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
+ {123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
+ {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
+ {130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
+ {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
+ {140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
+ {141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
+ {150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
+ {151, nullptr, "TryPopFromNotificationStorageChannel"},
+ {160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"},
+ {170, nullptr, "SetHdcpAuthenticationActivated"},
+ {180, nullptr, "GetLaunchRequiredVersion"},
+ {181, nullptr, "UpgradeLaunchRequiredVersion"},
+ {190, nullptr, "SendServerMaintenanceOverlayNotification"},
+ {200, nullptr, "GetLastApplicationExitReason"},
+ {500, nullptr, "StartContinuousRecordingFlushForDebug"},
+ {1000, nullptr, "CreateMovieMaker"},
+ {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationFunctions::~IApplicationFunctions() = default;
+
+Result IApplicationFunctions::PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
+ LaunchParameterKind launch_parameter_kind) {
+ LOG_INFO(Service_AM, "called, kind={}", launch_parameter_kind);
+
+ std::scoped_lock lk{m_applet->lock};
+
+ auto& channel = launch_parameter_kind == LaunchParameterKind::UserChannel
+ ? m_applet->user_channel_launch_parameter
+ : m_applet->preselected_user_launch_parameter;
+
+ if (channel.empty()) {
+ LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!",
+ launch_parameter_kind);
+ R_THROW(AM::ResultNoDataInChannel);
+ }
+
+ auto data = channel.back();
+ channel.pop_back();
+
+ *out_storage = std::make_shared<IStorage>(system, std::move(data));
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID user_id) {
+ LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
+
+ FileSys::SaveDataAttribute attribute{};
+ attribute.title_id = m_applet->program_id;
+ attribute.user_id = user_id.AsU128();
+ attribute.type = FileSys::SaveDataType::SaveData;
+
+ FileSys::VirtualDir save_data{};
+ R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
+ &save_data, FileSys::SaveDataSpaceId::NandUser, attribute));
+
+ *out_size = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
+ // FIXME: all of this stuff belongs to ns
+ // TODO(bunnei): This should be configurable
+ LOG_DEBUG(Service_AM, "called");
+
+ // Get supported languages from NACP, if possible
+ // Default to 0 (all languages supported)
+ u32 supported_languages = 0;
+
+ const auto res = [this] {
+ const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ auto metadata = pm.GetControlMetadata();
+ if (metadata.first != nullptr) {
+ return metadata;
+ }
+
+ const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
+ system.GetFileSystemController(),
+ system.GetContentProvider()};
+ return pm_update.GetControlMetadata();
+ }();
+
+ if (res.first != nullptr) {
+ supported_languages = res.first->GetSupportedLanguages();
+ }
+
+ // Call IApplicationManagerInterface implementation.
+ auto& service_manager = system.ServiceManager();
+ 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
+ NS::ApplicationLanguage desired_language{};
+ R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
+
+ // Convert to settings language code.
+ R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(out_language_code, desired_language));
+
+ LOG_DEBUG(Service_AM, "got desired_language={:016X}", *out_language_code);
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
+ LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(),
+ static_cast<u32>(terminate_result.GetModule()) + 2000,
+ terminate_result.GetDescription());
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->terminate_result = terminate_result;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
+ LOG_DEBUG(Service_AM, "called");
+
+ const auto res = [this] {
+ const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ auto metadata = pm.GetControlMetadata();
+ if (metadata.first != nullptr) {
+ return metadata;
+ }
+
+ const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
+ system.GetFileSystemController(),
+ system.GetContentProvider()};
+ return pm_update.GetControlMetadata();
+ }();
+
+ if (res.first != nullptr) {
+ const auto& version = res.first->GetVersionString();
+ std::memcpy(out_display_version->string.data(), version.data(),
+ std::min(version.size(), out_display_version->string.size()));
+ } else {
+ static constexpr char default_version[]{"1.0.0"};
+ std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version));
+ }
+
+ out_display_version->string[out_display_version->string.size() - 1] = '\0';
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
+ Common::UUID user_id, u64 normal_size,
+ u64 journal_size) {
+ LOG_DEBUG(Service_AM, "called with type={} user_id={} normal={:#x} journal={:#x}",
+ static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
+
+ system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
+ type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size});
+
+ // The following value is used to indicate the amount of space remaining on failure
+ // due to running out of space. Since we always succeed, this should be 0.
+ *out_required_size = 0;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
+ FileSys::SaveDataType type, Common::UUID user_id) {
+ LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
+
+ const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
+ type, m_applet->program_id, user_id.AsU128());
+
+ *out_normal_size = size.normal;
+ *out_journal_size = size.journal;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::CreateCacheStorage(Out<u32> out_target_media,
+ Out<u64> out_required_size, u16 index,
+ u64 normal_size, u64 journal_size) {
+ LOG_WARNING(Service_AM, "(STUBBED) called with index={} size={:#x} journal_size={:#x}", index,
+ normal_size, journal_size);
+
+ *out_target_media = 1; // Nand
+ *out_required_size = 0;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
+ Out<u64> out_max_journal_size) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ *out_max_normal_size = 0xFFFFFFF;
+ *out_max_journal_size = 0xFFFFFFF;
+
+ 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");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->home_button_long_pressed_blocked = true;
+ m_applet->home_button_short_pressed_blocked = true;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->home_button_long_pressed_blocked = false;
+ m_applet->home_button_short_pressed_blocked = false;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::BeginBlockingHomeButton(s64 timeout_ns) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, timeout_ns={}", timeout_ns);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->home_button_long_pressed_blocked = true;
+ m_applet->home_button_short_pressed_blocked = true;
+ m_applet->home_button_double_click_enabled = true;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::EndBlockingHomeButton() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->home_button_long_pressed_blocked = false;
+ m_applet->home_button_short_pressed_blocked = false;
+ m_applet->home_button_double_click_enabled = false;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_became_running = true;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_pseudo_device_id = {};
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::IsGamePlayRecordingSupported(
+ Out<bool> out_is_game_play_recording_supported) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_is_game_play_recording_supported = m_applet->game_play_recording_supported;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::InitializeGamePlayRecording(
+ u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::SetGamePlayRecordingState(
+ GamePlayRecordingState game_play_recording_state) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->game_play_recording_state = game_play_recording_state;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::EnableApplicationCrashReport(bool enabled) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->application_crash_report_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
+ s32 width, s32 height, u64 transfer_memory_size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::SetApplicationCopyrightImage(
+ s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
+ InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible);
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::QueryApplicationPlayStatistics(
+ Out<s32> out_entries,
+ OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_entries = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::QueryApplicationPlayStatisticsByUid(
+ Out<s32> out_entries,
+ OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
+ Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_entries = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, kind={}, value={}", kind, value);
+ ASSERT(kind == ProgramSpecifyKind::ExecuteProgram ||
+ kind == ProgramSpecifyKind::RestartProgram);
+
+ // Copy user channel ownership into the system so that it will be preserved
+ system.GetUserChannel() = m_applet->user_channel_launch_parameter;
+ system.ExecuteProgram(value);
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::ClearUserChannel() {
+ LOG_DEBUG(Service_AM, "called");
+ m_applet->user_channel_launch_parameter.clear();
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::UnpopToUserChannel(SharedPointer<IStorage> storage) {
+ LOG_DEBUG(Service_AM, "called");
+ m_applet->user_channel_launch_parameter.push_back(storage->GetData());
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetPreviousProgramIndex(Out<s32> out_previous_program_index) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_previous_program_index = m_applet->previous_program_index;
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_event = m_applet->gpu_error_detected_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_applet->friend_invitation_storage_channel_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
+ Out<SharedPointer<IStorage>> out_storage) {
+ LOG_INFO(Service_AM, "(STUBBED) called");
+ R_THROW(AM::ResultNoDataInChannel);
+}
+
+Result IApplicationFunctions::GetNotificationStorageChannelEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_applet->notification_storage_channel_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_applet->health_warning_disappeared_system_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationFunctions::PrepareForJit() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->jit_service_launched = true;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h
new file mode 100644
index 000000000..10025a152
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.h
@@ -0,0 +1,84 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/uuid.h"
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace FileSys {
+enum class SaveDataType : u8;
+}
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::AM {
+
+struct Applet;
+class IStorage;
+
+class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
+public:
+ explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~IApplicationFunctions() override;
+
+private:
+ Result PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
+ LaunchParameterKind launch_parameter_kind);
+ Result EnsureSaveData(Out<u64> out_size, Common::UUID user_id);
+ Result GetDesiredLanguage(Out<u64> out_language_code);
+ Result SetTerminateResult(Result terminate_result);
+ Result GetDisplayVersion(Out<DisplayVersion> out_display_version);
+ Result ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
+ Common::UUID user_id, u64 normal_size, u64 journal_size);
+ Result GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
+ FileSys::SaveDataType type, Common::UUID user_id);
+ 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);
+ Result EndBlockingHomeButton();
+ Result NotifyRunning(Out<bool> out_became_running);
+ Result GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id);
+ Result IsGamePlayRecordingSupported(Out<bool> out_is_game_play_recording_supported);
+ Result InitializeGamePlayRecording(
+ u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
+ Result SetGamePlayRecordingState(GamePlayRecordingState game_play_recording_state);
+ Result EnableApplicationCrashReport(bool enabled);
+ Result InitializeApplicationCopyrightFrameBuffer(
+ s32 width, s32 height, u64 transfer_memory_size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
+ Result SetApplicationCopyrightImage(
+ s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
+ InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data);
+ Result SetApplicationCopyrightVisibility(bool visible);
+ Result QueryApplicationPlayStatistics(
+ Out<s32> out_entries,
+ OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result QueryApplicationPlayStatisticsByUid(
+ Out<s32> out_entries,
+ OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
+ Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result ExecuteProgram(ProgramSpecifyKind kind, u64 value);
+ Result ClearUserChannel();
+ Result UnpopToUserChannel(SharedPointer<IStorage> storage);
+ Result GetPreviousProgramIndex(Out<s32> out_previous_program_index);
+ Result GetGpuErrorDetectedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetFriendInvitationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage);
+ Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result PrepareForJit();
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp
new file mode 100644
index 000000000..19d6a3b89
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy.cpp
@@ -0,0 +1,105 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/applet_common_functions.h"
+#include "core/hle/service/am/service/application_functions.h"
+#include "core/hle/service/am/service/application_proxy.h"
+#include "core/hle/service/am/service/audio_controller.h"
+#include "core/hle/service/am/service/common_state_getter.h"
+#include "core/hle/service/am/service/debug_functions.h"
+#include "core/hle/service/am/service/display_controller.h"
+#include "core/hle/service/am/service/library_applet_creator.h"
+#include "core/hle/service/am/service/process_winding_controller.h"
+#include "core/hle/service/am/service/self_controller.h"
+#include "core/hle/service/am/service/window_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> 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"},
+ {1, D<&IApplicationProxy::GetSelfController>, "GetSelfController"},
+ {2, D<&IApplicationProxy::GetWindowController>, "GetWindowController"},
+ {3, D<&IApplicationProxy::GetAudioController>, "GetAudioController"},
+ {4, D<&IApplicationProxy::GetDisplayController>, "GetDisplayController"},
+ {10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"},
+ {11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
+ {20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"},
+ {1000, D<&IApplicationProxy::GetDebugFunctions>, "GetDebugFunctions"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationProxy::~IApplicationProxy() = default;
+
+Result IApplicationProxy::GetAudioController(
+ Out<SharedPointer<IAudioController>> out_audio_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_audio_controller = std::make_shared<IAudioController>(system);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetDisplayController(
+ Out<SharedPointer<IDisplayController>> out_display_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetDebugFunctions(
+ Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_debug_functions = std::make_shared<IDebugFunctions>(system);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetWindowController(
+ Out<SharedPointer<IWindowController>> out_window_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
+ R_SUCCEED();
+}
+
+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);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetCommonStateGetter(
+ Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result IApplicationProxy::GetApplicationFunctions(
+ Out<SharedPointer<IApplicationFunctions>> out_application_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_application_functions = std::make_shared<IApplicationFunctions>(system, m_applet);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h
new file mode 100644
index 000000000..6da350df7
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy.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::AM {
+
+struct Applet;
+class IAudioController;
+class IApplicationFunctions;
+class ICommonStateGetter;
+class IDebugFunctions;
+class IDisplayController;
+class ILibraryAppletCreator;
+class IProcessWindingController;
+class ISelfController;
+class IWindowController;
+
+class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
+public:
+ explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
+ Kernel::KProcess* process);
+ ~IApplicationProxy();
+
+private:
+ Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
+ Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
+ Result GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
+ Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
+ Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
+ Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
+ Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
+ Result GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
+ Result GetApplicationFunctions(
+ Out<SharedPointer<IApplicationFunctions>> out_application_functions);
+
+private:
+ Kernel::KProcess* const m_process;
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp
new file mode 100644
index 000000000..fd66e77b9
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy_service.cpp
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/application_proxy.h"
+#include "core/hle/service/am/service/application_proxy_service.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IApplicationProxyService::IApplicationProxyService(Core::System& system_)
+ : ServiceFramework{system_, "appletOE"} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
+ };
+ RegisterHandlers(functions);
+}
+
+IApplicationProxyService::~IApplicationProxyService() = default;
+
+Result IApplicationProxyService::OpenApplicationProxy(
+ Out<SharedPointer<IApplicationProxy>> out_application_proxy, ClientProcessId pid,
+ InCopyHandle<Kernel::KProcess> process_handle) {
+ LOG_DEBUG(Service_AM, "called");
+
+ if (const auto applet = this->GetAppletFromProcessId(pid)) {
+ *out_application_proxy =
+ std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());
+ R_SUCCEED();
+ } else {
+ UNIMPLEMENTED();
+ R_THROW(ResultUnknown);
+ }
+}
+
+std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
+ return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h
new file mode 100644
index 000000000..8efafa31a
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy_service.h
@@ -0,0 +1,30 @@
+// 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"
+
+namespace Service {
+
+namespace AM {
+
+struct Applet;
+class IApplicationProxy;
+
+class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
+public:
+ explicit IApplicationProxyService(Core::System& system_);
+ ~IApplicationProxyService() override;
+
+private:
+ Result OpenApplicationProxy(Out<SharedPointer<IApplicationProxy>> out_application_proxy,
+ ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
+
+private:
+ std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
+};
+
+} // namespace AM
+} // namespace Service
diff --git a/src/core/hle/service/am/service/audio_controller.cpp b/src/core/hle/service/am/service/audio_controller.cpp
new file mode 100644
index 000000000..ad731c7bd
--- /dev/null
+++ b/src/core/hle/service/am/service/audio_controller.cpp
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/audio_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IAudioController::IAudioController(Core::System& system_)
+ : ServiceFramework{system_, "IAudioController"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"},
+ {1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"},
+ {2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
+ {3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
+ {4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAudioController::~IAudioController() = default;
+
+Result IAudioController::SetExpectedMasterVolume(f32 main_applet_volume,
+ f32 library_applet_volume) {
+ LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
+ main_applet_volume, library_applet_volume);
+
+ // Ensure the volume values remain within the 0-100% range
+ m_main_applet_volume = std::clamp(main_applet_volume, MinAllowedVolume, MaxAllowedVolume);
+ m_library_applet_volume = std::clamp(library_applet_volume, MinAllowedVolume, MaxAllowedVolume);
+
+ R_SUCCEED();
+}
+
+Result IAudioController::GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume) {
+ LOG_DEBUG(Service_AM, "called. main_applet_volume={}", m_main_applet_volume);
+ *out_main_applet_volume = m_main_applet_volume;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume) {
+ LOG_DEBUG(Service_AM, "called. library_applet_volume={}", m_library_applet_volume);
+ *out_library_applet_volume = m_library_applet_volume;
+ R_SUCCEED();
+}
+
+Result IAudioController::ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns) {
+ LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", volume, fade_time_ns);
+
+ m_main_applet_volume = std::clamp(volume, MinAllowedVolume, MaxAllowedVolume);
+ m_fade_time_ns = std::chrono::nanoseconds{fade_time_ns};
+
+ R_SUCCEED();
+}
+
+Result IAudioController::SetTransparentVolumeRate(f32 transparent_volume_rate) {
+ LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate);
+
+ // Clamp volume range to 0-100%.
+ m_transparent_volume_rate =
+ std::clamp(transparent_volume_rate, MinAllowedVolume, MaxAllowedVolume);
+
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/audio_controller.h b/src/core/hle/service/am/service/audio_controller.h
new file mode 100644
index 000000000..4b0f3f9ae
--- /dev/null
+++ b/src/core/hle/service/am/service/audio_controller.h
@@ -0,0 +1,37 @@
+// 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::AM {
+
+class IAudioController final : public ServiceFramework<IAudioController> {
+public:
+ explicit IAudioController(Core::System& system_);
+ ~IAudioController() override;
+
+private:
+ Result SetExpectedMasterVolume(f32 main_applet_volume, f32 library_applet_volume);
+ Result GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume);
+ Result GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume);
+ Result ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns);
+ Result SetTransparentVolumeRate(f32 transparent_volume_rate);
+
+ static constexpr float MinAllowedVolume = 0.0f;
+ static constexpr float MaxAllowedVolume = 1.0f;
+
+ float m_main_applet_volume{0.25f};
+ float m_library_applet_volume{MaxAllowedVolume};
+ float m_transparent_volume_rate{MinAllowedVolume};
+
+ // Volume transition fade time in nanoseconds.
+ // e.g. If the main applet volume was 0% and was changed to 50%
+ // with a fade of 50ns, then over the course of 50ns,
+ // the volume will gradually fade up to 50%
+ std::chrono::nanoseconds m_fade_time_ns{0};
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp
new file mode 100644
index 000000000..548498e83
--- /dev/null
+++ b/src/core/hle/service/am/service/common_state_getter.cpp
@@ -0,0 +1,278 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/service/common_state_getter.h"
+#include "core/hle/service/am/service/lock_accessor.h"
+#include "core/hle/service/apm/apm_interface.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/pm/pm.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::AM {
+
+ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "ICommonStateGetter"}, m_applet{std::move(applet)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"},
+ {1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"},
+ {2, nullptr, "GetThisAppletKind"},
+ {3, nullptr, "AllowToEnterSleep"},
+ {4, nullptr, "DisallowToEnterSleep"},
+ {5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"},
+ {6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"},
+ {7, nullptr, "GetCradleStatus"},
+ {8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"},
+ {9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"},
+ {10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"},
+ {11, nullptr, "ReleaseSleepLock"},
+ {12, nullptr, "ReleaseSleepLockTransiently"},
+ {13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"},
+ {14, nullptr, "GetWakeupCount"},
+ {20, nullptr, "PushToGeneralChannel"},
+ {30, nullptr, "GetHomeButtonReaderLockAccessor"},
+ {31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"},
+ {32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"},
+ {40, nullptr, "GetCradleFwVersion"},
+ {50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"},
+ {51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"},
+ {52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"},
+ {53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx"},
+ {54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx"},
+ {55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection"},
+ {59, nullptr, "SetVrPositionForDebug"},
+ {60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"},
+ {61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"},
+ {62, nullptr, "GetHdcpAuthenticationState"},
+ {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
+ {64, nullptr, "SetTvPowerStateMatchingMode"},
+ {65, nullptr, "GetApplicationIdByContentActionName"},
+ {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
+ {67, nullptr, "CancelCpuBoostMode"},
+ {68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"},
+ {80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"},
+ {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
+ {91, nullptr, "GetCurrentPerformanceConfiguration"},
+ {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
+ {110, nullptr, "OpenMyGpuErrorHandler"},
+ {120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"},
+ {200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
+ {300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
+ {400, nullptr, "ActivateMigrationService"},
+ {401, nullptr, "DeactivateMigrationService"},
+ {500, nullptr, "DisableSleepTillShutdown"},
+ {501, nullptr, "SuppressDisablingSleepTemporarily"},
+ {502, nullptr, "IsSleepEnabled"},
+ {503, nullptr, "IsDisablingSleepSuppressed"},
+ {900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ICommonStateGetter::~ICommonStateGetter() = default;
+
+Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = &m_applet->message_queue.GetMessageReceiveEvent();
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
+ LOG_DEBUG(Service_AM, "called");
+
+ *out_applet_message = m_applet->message_queue.PopMessage();
+ if (*out_applet_message == AppletMessage::None) {
+ LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
+ R_THROW(AM::ResultNoMessages);
+ }
+
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state) {
+ LOG_DEBUG(Service_AM, "called");
+
+ std::scoped_lock lk{m_applet->lock};
+ *out_focus_state = m_applet->focus_state;
+
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::RequestToAcquireSleepLock() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ // Sleep lock is acquired immediately.
+ m_applet->sleep_lock_event.Signal();
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetAcquiredSleepLockEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_AM, "called");
+ *out_event = m_applet->sleep_lock_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetReaderLockAccessorEx(
+ Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
+ LOG_INFO(Service_AM, "called, button_type={}", button_type);
+ *out_lock_accessor = std::make_shared<ILockAccessor>(system);
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetWriterLockAccessorEx(
+ Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
+ LOG_INFO(Service_AM, "called, button_type={}", button_type);
+ *out_lock_accessor = std::make_shared<ILockAccessor>(system);
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = &m_applet->message_queue.GetOperationModeChangedEvent();
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetOperationMode(Out<OperationMode> out_operation_mode) {
+ const bool use_docked_mode{Settings::IsDockedMode()};
+ LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
+ *out_operation_mode = use_docked_mode ? OperationMode::Docked : OperationMode::Handheld;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_performance_mode = system.GetAPMController().GetCurrentPerformanceMode();
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetBootMode(Out<PM::SystemBootMode> out_boot_mode) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_boot_mode = Service::PM::SystemBootMode::Normal;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled) {
+ LOG_DEBUG(Service_AM, "called");
+
+ std::scoped_lock lk{m_applet->lock};
+ *out_is_vr_mode_enabled = m_applet->vr_mode_enabled;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::SetVrModeEnabled(bool is_vr_mode_enabled) {
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->vr_mode_enabled = is_vr_mode_enabled;
+ LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled ? "on" : "off");
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled) {
+ LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
+ is_lcd_backlight_off_enabled);
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::BeginVrModeEx() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->vr_mode_enabled = true;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::EndVrModeEx() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->vr_mode_enabled = false;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::IsInControllerFirmwareUpdateSection(
+ Out<bool> out_is_in_controller_firmware_update_section) {
+ LOG_INFO(Service_AM, "called");
+ *out_is_in_controller_firmware_update_section = false;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height) {
+ LOG_DEBUG(Service_AM, "called");
+
+ if (Settings::IsDockedMode()) {
+ *out_width = static_cast<u32>(Service::VI::DisplayResolution::DockedWidth);
+ *out_height = static_cast<u32>(Service::VI::DisplayResolution::DockedHeight);
+ } else {
+ *out_width = static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth);
+ *out_height = static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight);
+ }
+
+ R_SUCCEED();
+}
+
+void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
+
+ const auto& sm = system.ServiceManager();
+ const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
+ ASSERT(apm_sys != nullptr);
+
+ apm_sys->SetCpuBoostMode(ctx);
+}
+
+Result ICommonStateGetter::GetBuiltInDisplayType(Out<s32> out_display_type) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_display_type = 0;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType type) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, type={}", type);
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_operation_mode_system_info = 0;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetAppletLaunchedHistory(
+ Out<s32> out_count, OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids) {
+ LOG_INFO(Service_AM, "called");
+
+ std::shared_ptr<Applet> current_applet = m_applet;
+
+ for (*out_count = 0;
+ *out_count < static_cast<s32>(out_applet_ids.size()) && current_applet != nullptr;
+ /* ... */) {
+ out_applet_ids[(*out_count)++] = current_applet->applet_id;
+ current_applet = current_applet->caller_applet.lock();
+ }
+
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::GetSettingsPlatformRegion(
+ Out<SysPlatformRegion> out_settings_platform_region) {
+ LOG_INFO(Service_AM, "called");
+ *out_settings_platform_region = SysPlatformRegion::Global;
+ R_SUCCEED();
+}
+
+Result ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/common_state_getter.h b/src/core/hle/service/am/service/common_state_getter.h
new file mode 100644
index 000000000..5a8dca3d6
--- /dev/null
+++ b/src/core/hle/service/am/service/common_state_getter.h
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/apm/apm_controller.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/pm/pm.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::AM {
+
+struct Applet;
+class ILockAccessor;
+
+class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
+public:
+ explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
+ ~ICommonStateGetter() override;
+
+private:
+ Result GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result ReceiveMessage(Out<AppletMessage> out_applet_message);
+ Result GetCurrentFocusState(Out<FocusState> out_focus_state);
+ Result RequestToAcquireSleepLock();
+ Result GetAcquiredSleepLockEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetReaderLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
+ u32 button_type);
+ Result GetWriterLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
+ u32 button_type);
+ Result GetDefaultDisplayResolutionChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetOperationMode(Out<OperationMode> out_operation_mode);
+ Result GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode);
+ Result GetBootMode(Out<PM::SystemBootMode> out_boot_mode);
+ Result IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled);
+ Result SetVrModeEnabled(bool is_vr_mode_enabled);
+ Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled);
+ Result BeginVrModeEx();
+ Result EndVrModeEx();
+ Result IsInControllerFirmwareUpdateSection(
+ Out<bool> out_is_in_controller_firmware_update_section);
+ Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height);
+ Result GetBuiltInDisplayType(Out<s32> out_display_type);
+ Result PerformSystemButtonPressingIfInFocus(SystemButtonType type);
+ Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
+ Result GetAppletLaunchedHistory(Out<s32> out_count,
+ OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
+ Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region);
+ Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
+
+ void SetCpuBoostMode(HLERequestContext& ctx);
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.cpp b/src/core/hle/service/am/service/cradle_firmware_updater.cpp
new file mode 100644
index 000000000..0a8af0858
--- /dev/null
+++ b/src/core/hle/service/am/service/cradle_firmware_updater.cpp
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/cradle_firmware_updater.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_)
+ : ServiceFramework{system_, "ICradleFirmwareUpdater"},
+ m_context{system, "ICradleFirmwareUpdater"}, m_cradle_device_info_event{m_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"},
+ {1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"},
+ {2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"},
+ {3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"},
+ {4, nullptr, "GetUpdateProgressInfo"},
+ {5, nullptr, "GetLastInternalResult"},
+
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ICradleFirmwareUpdater::~ICradleFirmwareUpdater() = default;
+
+Result ICradleFirmwareUpdater::StartUpdate() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ICradleFirmwareUpdater::FinishUpdate() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ICradleFirmwareUpdater::GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_cradle_device_info = {};
+ R_SUCCEED();
+}
+
+Result ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_event = m_cradle_device_info_event.GetHandle();
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.h b/src/core/hle/service/am/service/cradle_firmware_updater.h
new file mode 100644
index 000000000..3e803f0ae
--- /dev/null
+++ b/src/core/hle/service/am/service/cradle_firmware_updater.h
@@ -0,0 +1,37 @@
+// 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/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+struct CradleDeviceInfo {
+ bool unknown0;
+ bool unknown1;
+ bool unknown2;
+ u64 unknown3;
+};
+static_assert(sizeof(CradleDeviceInfo) == 0x10, "CradleDeviceInfo has incorrect size");
+
+class ICradleFirmwareUpdater final : public ServiceFramework<ICradleFirmwareUpdater> {
+public:
+ explicit ICradleFirmwareUpdater(Core::System& system_);
+ ~ICradleFirmwareUpdater() override;
+
+private:
+ Result StartUpdate();
+ Result FinishUpdate();
+ Result GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info);
+ Result GetCradleDeviceInfoChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+private:
+ KernelHelpers::ServiceContext m_context;
+ Event m_cradle_device_info_event;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/debug_functions.cpp b/src/core/hle/service/am/service/debug_functions.cpp
new file mode 100644
index 000000000..fcac4776d
--- /dev/null
+++ b/src/core/hle/service/am/service/debug_functions.cpp
@@ -0,0 +1,43 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/debug_functions.h"
+
+namespace Service::AM {
+
+IDebugFunctions::IDebugFunctions(Core::System& system_)
+ : ServiceFramework{system_, "IDebugFunctions"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
+ {1, nullptr, "OpenMainApplication"},
+ {10, nullptr, "PerformSystemButtonPressing"},
+ {20, nullptr, "InvalidateTransitionLayer"},
+ {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
+ {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
+ {40, nullptr, "GetAppletResourceUsageInfo"},
+ {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
+ {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
+ {100, nullptr, "SetCpuBoostModeForApplet"},
+ {101, nullptr, "CancelCpuBoostModeForApplet"},
+ {110, nullptr, "PushToAppletBoundChannelForDebug"},
+ {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
+ {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
+ {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
+ {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
+ {130, nullptr, "FriendInvitationSetApplicationParameter"},
+ {131, nullptr, "FriendInvitationClearApplicationParameter"},
+ {132, nullptr, "FriendInvitationPushApplicationParameter"},
+ {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
+ {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
+ {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
+ {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDebugFunctions::~IDebugFunctions() = default;
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/service/debug_functions.h
index d55968743..d55968743 100644
--- a/src/core/hle/service/am/debug_functions.h
+++ b/src/core/hle/service/am/service/debug_functions.h
diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp
new file mode 100644
index 000000000..ed71f9093
--- /dev/null
+++ b/src/core/hle/service/am/service/display_controller.cpp
@@ -0,0 +1,105 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/result.h"
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/service/display_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
+ : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetLastForegroundCaptureImage"},
+ {1, nullptr, "UpdateLastForegroundCaptureImage"},
+ {2, nullptr, "GetLastApplicationCaptureImage"},
+ {3, nullptr, "GetCallerAppletCaptureImage"},
+ {4, nullptr, "UpdateCallerAppletCaptureImage"},
+ {5, nullptr, "GetLastForegroundCaptureImageEx"},
+ {6, nullptr, "GetLastApplicationCaptureImageEx"},
+ {7, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"},
+ {8, D<&IDisplayController::TakeScreenShotOfOwnLayer>, "TakeScreenShotOfOwnLayer"},
+ {9, nullptr, "CopyBetweenCaptureBuffers"},
+ {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
+ {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
+ {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
+ {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
+ {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
+ {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
+ {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
+ {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
+ {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
+ {20, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"},
+ {21, nullptr, "ClearAppletTransitionBuffer"},
+ {22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"},
+ {23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"},
+ {24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"},
+ {25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"},
+ {26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"},
+ {27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"},
+ {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDisplayController::~IDisplayController() = default;
+
+Result IDisplayController::GetCallerAppletCaptureImageEx(
+ Out<bool> out_was_written, OutBuffer<BufferAttr_HipcMapAlias> out_image_data) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_was_written = true;
+ R_SUCCEED();
+}
+
+Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}",
+ unknown0, fbshare_layer_index, color);
+ R_SUCCEED();
+}
+
+Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
+ Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
+ out_fbshare_layer_index));
+}
+
+Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
+ Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
+ out_fbshare_layer_index));
+}
+
+Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
+ Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
+ out_fbshare_layer_index));
+}
+
+Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/display_controller.h b/src/core/hle/service/am/service/display_controller.h
new file mode 100644
index 000000000..406fae21a
--- /dev/null
+++ b/src/core/hle/service/am/service/display_controller.h
@@ -0,0 +1,36 @@
+// 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::AM {
+
+struct Applet;
+
+class IDisplayController final : public ServiceFramework<IDisplayController> {
+public:
+ explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
+ ~IDisplayController() override;
+
+private:
+ Result GetCallerAppletCaptureImageEx(Out<bool> out_was_written,
+ OutBuffer<BufferAttr_HipcMapAlias> out_image_data);
+ Result TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index);
+ Result ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color);
+ Result AcquireLastForegroundCaptureSharedBuffer(Out<bool> out_was_written,
+ Out<s32> out_fbshare_layer_index);
+ Result ReleaseLastForegroundCaptureSharedBuffer();
+ Result AcquireCallerAppletCaptureSharedBuffer(Out<bool> out_was_written,
+ Out<s32> out_fbshare_layer_index);
+ Result ReleaseCallerAppletCaptureSharedBuffer();
+ Result AcquireLastApplicationCaptureSharedBuffer(Out<bool> out_was_written,
+ Out<s32> out_fbshare_layer_index);
+ Result ReleaseLastApplicationCaptureSharedBuffer();
+
+ const std::shared_ptr<Applet> applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/global_state_controller.cpp b/src/core/hle/service/am/service/global_state_controller.cpp
new file mode 100644
index 000000000..dba5d3613
--- /dev/null
+++ b/src/core/hle/service/am/service/global_state_controller.cpp
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/cradle_firmware_updater.h"
+#include "core/hle/service/am/service/global_state_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IGlobalStateController::IGlobalStateController(Core::System& system_)
+ : ServiceFramework{system_, "IGlobalStateController"},
+ m_context{system_, "IGlobalStateController"}, m_hdcp_authentication_failed_event{m_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestToEnterSleep"},
+ {1, nullptr, "EnterSleep"},
+ {2, nullptr, "StartSleepSequence"},
+ {3, nullptr, "StartShutdownSequence"},
+ {4, nullptr, "StartRebootSequence"},
+ {9, nullptr, "IsAutoPowerDownRequested"},
+ {10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
+ {11, nullptr, "NotifyCecSettingsChanged"},
+ {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
+ {13, nullptr, "UpdateDefaultDisplayResolution"},
+ {14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"},
+ {15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"},
+ {30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IGlobalStateController::~IGlobalStateController() = default;
+
+Result IGlobalStateController::LoadAndApplyIdlePolicySettings() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IGlobalStateController::ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot) {
+ LOG_INFO(Service_AM, "called");
+ *out_should_sleep_on_boot = false;
+ R_SUCCEED();
+}
+
+Result IGlobalStateController::GetHdcpAuthenticationFailedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_AM, "called");
+ *out_event = m_hdcp_authentication_failed_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IGlobalStateController::OpenCradleFirmwareUpdater(
+ Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater) {
+ LOG_INFO(Service_AM, "called");
+ *out_cradle_firmware_updater = std::make_shared<ICradleFirmwareUpdater>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/global_state_controller.h b/src/core/hle/service/am/service/global_state_controller.h
new file mode 100644
index 000000000..67c753513
--- /dev/null
+++ b/src/core/hle/service/am/service/global_state_controller.h
@@ -0,0 +1,31 @@
+// 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/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ICradleFirmwareUpdater;
+
+class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
+public:
+ explicit IGlobalStateController(Core::System& system_);
+ ~IGlobalStateController() override;
+
+private:
+ Result LoadAndApplyIdlePolicySettings();
+ Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);
+ Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result OpenCradleFirmwareUpdater(
+ Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater);
+
+ KernelHelpers::ServiceContext m_context;
+ Event m_hdcp_authentication_failed_event;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/home_menu_functions.cpp b/src/core/hle/service/am/service/home_menu_functions.cpp
new file mode 100644
index 000000000..0c4d24b58
--- /dev/null
+++ b/src/core/hle/service/am/service/home_menu_functions.cpp
@@ -0,0 +1,74 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/result.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/home_menu_functions.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)},
+ m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
+ {11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"},
+ {12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"},
+ {20, nullptr, "PopFromGeneralChannel"},
+ {21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"},
+ {30, nullptr, "GetHomeButtonWriterLockAccessor"},
+ {31, nullptr, "GetWriterLockAccessorEx"},
+ {40, nullptr, "IsSleepEnabled"},
+ {41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"},
+ {50, nullptr, "LaunchSystemApplet"},
+ {51, nullptr, "LaunchStarter"},
+ {100, nullptr, "PopRequestLaunchApplicationForDebug"},
+ {110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"},
+ {200, nullptr, "LaunchDevMenu"},
+ {1000, nullptr, "SetLastApplicationExitReason"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IHomeMenuFunctions::~IHomeMenuFunctions() = default;
+
+Result IHomeMenuFunctions::RequestToGetForeground() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IHomeMenuFunctions::LockForeground() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IHomeMenuFunctions::UnlockForeground() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_AM, "called");
+ *out_event = m_pop_from_general_channel_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IHomeMenuFunctions::IsRebootEnabled(Out<bool> out_is_reboot_enbaled) {
+ LOG_INFO(Service_AM, "called");
+ *out_is_reboot_enbaled = true;
+ R_SUCCEED();
+}
+
+Result IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug(
+ Out<bool> out_is_force_terminate_application_disabled_for_debug) {
+ LOG_INFO(Service_AM, "called");
+ *out_is_force_terminate_application_disabled_for_debug = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/home_menu_functions.h b/src/core/hle/service/am/service/home_menu_functions.h
new file mode 100644
index 000000000..caf6fbaab
--- /dev/null
+++ b/src/core/hle/service/am/service/home_menu_functions.h
@@ -0,0 +1,34 @@
+// 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/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+struct Applet;
+
+class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
+public:
+ explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~IHomeMenuFunctions() override;
+
+private:
+ Result RequestToGetForeground();
+ Result LockForeground();
+ Result UnlockForeground();
+ Result GetPopFromGeneralChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result IsRebootEnabled(Out<bool> out_is_reboot_enbaled);
+ Result IsForceTerminateApplicationDisabledForDebug(
+ Out<bool> out_is_force_terminate_application_disabled_for_debug);
+
+ const std::shared_ptr<Applet> m_applet;
+ KernelHelpers::ServiceContext m_context;
+ Event m_pop_from_general_channel_event;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp
new file mode 100644
index 000000000..0c2426d4b
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_accessor.cpp
@@ -0,0 +1,157 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_data_broker.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/service/library_applet_accessor.h"
+#include "core/hle/service/am/service/storage.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
+ std::shared_ptr<AppletDataBroker> broker,
+ std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "ILibraryAppletAccessor"}, m_broker{std::move(broker)},
+ m_applet{std::move(applet)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
+ {1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"},
+ {10, D<&ILibraryAppletAccessor::Start>, "Start"},
+ {20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"},
+ {25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"},
+ {30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"},
+ {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
+ {60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero"},
+ {100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"},
+ {101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"},
+ {102, nullptr, "PushExtraStorage"},
+ {103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"},
+ {104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"},
+ {105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
+ {106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
+ {110, nullptr, "NeedsToExitProcess"},
+ {120, nullptr, "GetLibraryAppletInfo"},
+ {150, nullptr, "RequestForAppletToGetForeground"},
+ {160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
+
+Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_broker->GetStateChangedEvent().GetHandle();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_is_completed = m_broker->IsCompleted();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_result = m_applet->terminate_result;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
+ LOG_INFO(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::Start() {
+ LOG_DEBUG(Service_AM, "called");
+ m_applet->process->Run();
+ FrontendExecute();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::RequestExit() {
+ LOG_DEBUG(Service_AM, "called");
+ m_applet->message_queue.RequestExit();
+ FrontendRequestExit();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::Terminate() {
+ LOG_DEBUG(Service_AM, "called");
+ m_applet->process->Terminate();
+ FrontendRequestExit();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::PushInData(SharedPointer<IStorage> storage) {
+ LOG_DEBUG(Service_AM, "called");
+ m_broker->GetInData().Push(storage);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_storage) {
+ LOG_DEBUG(Service_AM, "called");
+ R_RETURN(m_broker->GetOutData().Pop(out_storage.Get()));
+}
+
+Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer<IStorage> storage) {
+ LOG_DEBUG(Service_AM, "called");
+ m_broker->GetInteractiveInData().Push(storage);
+ FrontendExecuteInteractive();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage) {
+ LOG_DEBUG(Service_AM, "called");
+ R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get()));
+}
+
+Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_broker->GetOutData().GetEvent();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_event = m_broker->GetInteractiveOutData().GetEvent();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(Out<u64> out_handle) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
+ // actually used anywhere
+ *out_handle = 0xdeadbeef;
+ R_SUCCEED();
+}
+
+void ILibraryAppletAccessor::FrontendExecute() {
+ if (m_applet->frontend) {
+ m_applet->frontend->Initialize();
+ m_applet->frontend->Execute();
+ }
+}
+
+void ILibraryAppletAccessor::FrontendExecuteInteractive() {
+ if (m_applet->frontend) {
+ m_applet->frontend->ExecuteInteractive();
+ m_applet->frontend->Execute();
+ }
+}
+
+void ILibraryAppletAccessor::FrontendRequestExit() {
+ if (m_applet->frontend) {
+ m_applet->frontend->RequestExit();
+ }
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_accessor.h b/src/core/hle/service/am/service/library_applet_accessor.h
new file mode 100644
index 000000000..97d3b6c8a
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_accessor.h
@@ -0,0 +1,45 @@
+// 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::AM {
+
+class AppletDataBroker;
+struct Applet;
+class IStorage;
+
+class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
+public:
+ explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<AppletDataBroker> broker,
+ std::shared_ptr<Applet> applet);
+ ~ILibraryAppletAccessor();
+
+private:
+ Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result IsCompleted(Out<bool> out_is_completed);
+ Result GetResult(Out<Result> out_result);
+ Result PresetLibraryAppletGpuTimeSliceZero();
+ Result Start();
+ Result RequestExit();
+ Result Terminate();
+ Result PushInData(SharedPointer<IStorage> storage);
+ Result PopOutData(Out<SharedPointer<IStorage>> out_storage);
+ Result PushInteractiveInData(SharedPointer<IStorage> storage);
+ Result PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage);
+ Result GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetPopInteractiveOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetIndirectLayerConsumerHandle(Out<u64> out_handle);
+
+ void FrontendExecute();
+ void FrontendExecuteInteractive();
+ void FrontendRequestExit();
+
+ const std::shared_ptr<AppletDataBroker> m_broker;
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp
new file mode 100644
index 000000000..c97358d81
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_creator.cpp
@@ -0,0 +1,268 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/am/applet_data_broker.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/library_applet_storage.h"
+#include "core/hle/service/am/service/library_applet_accessor.h"
+#include "core/hle/service/am/service/library_applet_creator.h"
+#include "core/hle/service/am/service/storage.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::AM {
+
+namespace {
+
+bool ShouldCreateGuestApplet(AppletId applet_id) {
+#define X(Name, name) \
+ if (applet_id == AppletId::Name && \
+ Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \
+ return false; \
+ }
+
+ X(Cabinet, cabinet)
+ X(Controller, controller)
+ X(DataErase, data_erase)
+ X(Error, error)
+ X(NetConnect, net_connect)
+ X(ProfileSelect, player_select)
+ X(SoftwareKeyboard, swkbd)
+ X(MiiEdit, mii_edit)
+ X(Web, web)
+ X(Shop, shop)
+ X(PhotoViewer, photo_viewer)
+ X(OfflineWeb, offline_web)
+ X(LoginShare, login_share)
+ X(WebAuth, wifi_web_auth)
+ X(MyPage, my_page)
+
+#undef X
+
+ return true;
+}
+
+AppletProgramId AppletIdToProgramId(AppletId applet_id) {
+ switch (applet_id) {
+ case AppletId::OverlayDisplay:
+ return AppletProgramId::OverlayDisplay;
+ case AppletId::QLaunch:
+ return AppletProgramId::QLaunch;
+ case AppletId::Starter:
+ return AppletProgramId::Starter;
+ case AppletId::Auth:
+ return AppletProgramId::Auth;
+ case AppletId::Cabinet:
+ return AppletProgramId::Cabinet;
+ case AppletId::Controller:
+ return AppletProgramId::Controller;
+ case AppletId::DataErase:
+ return AppletProgramId::DataErase;
+ case AppletId::Error:
+ return AppletProgramId::Error;
+ case AppletId::NetConnect:
+ return AppletProgramId::NetConnect;
+ case AppletId::ProfileSelect:
+ return AppletProgramId::ProfileSelect;
+ case AppletId::SoftwareKeyboard:
+ return AppletProgramId::SoftwareKeyboard;
+ case AppletId::MiiEdit:
+ return AppletProgramId::MiiEdit;
+ case AppletId::Web:
+ return AppletProgramId::Web;
+ case AppletId::Shop:
+ return AppletProgramId::Shop;
+ case AppletId::PhotoViewer:
+ return AppletProgramId::PhotoViewer;
+ case AppletId::Settings:
+ return AppletProgramId::Settings;
+ case AppletId::OfflineWeb:
+ return AppletProgramId::OfflineWeb;
+ case AppletId::LoginShare:
+ return AppletProgramId::LoginShare;
+ case AppletId::WebAuth:
+ return AppletProgramId::WebAuth;
+ case AppletId::MyPage:
+ return AppletProgramId::MyPage;
+ default:
+ return static_cast<AppletProgramId>(0);
+ }
+}
+
+std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
+ std::shared_ptr<Applet> caller_applet,
+ AppletId applet_id,
+ LibraryAppletMode mode) {
+ const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
+ if (program_id == 0) {
+ // Unknown applet
+ return {};
+ }
+
+ // TODO: enable other versions of applets
+ enum : u8 {
+ Firmware1400 = 14,
+ Firmware1500 = 15,
+ Firmware1600 = 16,
+ Firmware1700 = 17,
+ };
+
+ auto process = std::make_unique<Process>(system);
+ if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
+ // Couldn't initialize the guest process
+ return {};
+ }
+
+ const auto applet = std::make_shared<Applet>(system, std::move(process));
+ applet->program_id = program_id;
+ applet->applet_id = applet_id;
+ applet->type = AppletType::LibraryApplet;
+ applet->library_applet_mode = mode;
+
+ // Set focus state
+ switch (mode) {
+ case LibraryAppletMode::AllForeground:
+ case LibraryAppletMode::NoUi:
+ case LibraryAppletMode::PartialForeground:
+ case LibraryAppletMode::PartialForegroundIndirectDisplay:
+ applet->hid_registration.EnableAppletToGetInput(true);
+ applet->focus_state = FocusState::InFocus;
+ applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
+ break;
+ case LibraryAppletMode::AllForegroundInitiallyHidden:
+ applet->hid_registration.EnableAppletToGetInput(false);
+ applet->focus_state = FocusState::NotInFocus;
+ applet->display_layer_manager.SetWindowVisibility(false);
+ applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
+ break;
+ }
+
+ auto broker = std::make_shared<AppletDataBroker>(system);
+ applet->caller_applet = caller_applet;
+ applet->caller_applet_broker = broker;
+
+ system.GetAppletManager().InsertApplet(applet);
+
+ return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
+}
+
+std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
+ std::shared_ptr<Applet> caller_applet,
+ AppletId applet_id,
+ LibraryAppletMode mode) {
+ const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
+
+ auto process = std::make_unique<Process>(system);
+ auto applet = std::make_shared<Applet>(system, std::move(process));
+ applet->program_id = program_id;
+ applet->applet_id = applet_id;
+ applet->type = AppletType::LibraryApplet;
+ applet->library_applet_mode = mode;
+
+ auto storage = std::make_shared<AppletDataBroker>(system);
+ applet->caller_applet = caller_applet;
+ applet->caller_applet_broker = storage;
+ applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
+
+ return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
+}
+
+} // namespace
+
+ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} {
+ static const FunctionInfo functions[] = {
+ {0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
+ {1, nullptr, "TerminateAllLibraryApplets"},
+ {2, nullptr, "AreAnyLibraryAppletsLeft"},
+ {10, D<&ILibraryAppletCreator::CreateStorage>, "CreateStorage"},
+ {11, D<&ILibraryAppletCreator::CreateTransferMemoryStorage>, "CreateTransferMemoryStorage"},
+ {12, D<&ILibraryAppletCreator::CreateHandleStorage>, "CreateHandleStorage"},
+ };
+ RegisterHandlers(functions);
+}
+
+ILibraryAppletCreator::~ILibraryAppletCreator() = default;
+
+Result ILibraryAppletCreator::CreateLibraryApplet(
+ Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
+ LibraryAppletMode library_applet_mode) {
+ LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={}", applet_id,
+ library_applet_mode);
+
+ std::shared_ptr<ILibraryAppletAccessor> library_applet;
+ if (ShouldCreateGuestApplet(applet_id)) {
+ library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode);
+ }
+ if (!library_applet) {
+ library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode);
+ }
+ if (!library_applet) {
+ LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
+ R_THROW(ResultUnknown);
+ }
+
+ // Applet is created, can now be launched.
+ m_applet->library_applet_launchable_event.Signal();
+ *out_library_applet_accessor = library_applet;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletCreator::CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size) {
+ LOG_DEBUG(Service_AM, "called, size={}", size);
+
+ if (size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ R_THROW(ResultUnknown);
+ }
+
+ *out_storage = std::make_shared<IStorage>(system, AM::CreateStorage(std::vector<u8>(size)));
+ R_SUCCEED();
+}
+
+Result ILibraryAppletCreator::CreateTransferMemoryStorage(
+ Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
+ LOG_DEBUG(Service_AM, "called, is_writable={} size={}", is_writable, size);
+
+ if (size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ R_THROW(ResultUnknown);
+ }
+
+ if (!transfer_memory_handle) {
+ LOG_ERROR(Service_AM, "transfer_memory_handle is null");
+ R_THROW(ResultUnknown);
+ }
+
+ *out_storage = std::make_shared<IStorage>(
+ system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(),
+ transfer_memory_handle.Get(), is_writable, size));
+ R_SUCCEED();
+}
+
+Result ILibraryAppletCreator::CreateHandleStorage(
+ Out<SharedPointer<IStorage>> out_storage, s64 size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
+ LOG_DEBUG(Service_AM, "called, size={}", size);
+
+ if (size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ R_THROW(ResultUnknown);
+ }
+
+ if (!transfer_memory_handle) {
+ LOG_ERROR(Service_AM, "transfer_memory_handle is null");
+ R_THROW(ResultUnknown);
+ }
+
+ *out_storage = std::make_shared<IStorage>(
+ system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(),
+ transfer_memory_handle.Get(), size));
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_creator.h b/src/core/hle/service/am/service/library_applet_creator.h
new file mode 100644
index 000000000..fe6d40eb3
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_creator.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+struct Applet;
+class ILibraryAppletAccessor;
+class IStorage;
+
+class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
+public:
+ explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~ILibraryAppletCreator() override;
+
+private:
+ Result CreateLibraryApplet(
+ Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
+ LibraryAppletMode library_applet_mode);
+ Result CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size);
+ Result CreateTransferMemoryStorage(
+ Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
+ Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
+ InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp
new file mode 100644
index 000000000..58e709347
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_proxy.cpp
@@ -0,0 +1,132 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/applet_common_functions.h"
+#include "core/hle/service/am/service/audio_controller.h"
+#include "core/hle/service/am/service/common_state_getter.h"
+#include "core/hle/service/am/service/debug_functions.h"
+#include "core/hle/service/am/service/display_controller.h"
+#include "core/hle/service/am/service/global_state_controller.h"
+#include "core/hle/service/am/service/home_menu_functions.h"
+#include "core/hle/service/am/service/library_applet_creator.h"
+#include "core/hle/service/am/service/library_applet_proxy.h"
+#include "core/hle/service/am/service/library_applet_self_accessor.h"
+#include "core/hle/service/am/service/process_winding_controller.h"
+#include "core/hle/service/am/service/self_controller.h"
+#include "core/hle/service/am/service/window_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> 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"},
+ {1, D<&ILibraryAppletProxy::GetSelfController>, "GetSelfController"},
+ {2, D<&ILibraryAppletProxy::GetWindowController>, "GetWindowController"},
+ {3, D<&ILibraryAppletProxy::GetAudioController>, "GetAudioController"},
+ {4, D<&ILibraryAppletProxy::GetDisplayController>, "GetDisplayController"},
+ {10, D<&ILibraryAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
+ {11, D<&ILibraryAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
+ {20, D<&ILibraryAppletProxy::OpenLibraryAppletSelfAccessor>, "OpenLibraryAppletSelfAccessor"},
+ {21, D<&ILibraryAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
+ {22, D<&ILibraryAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
+ {23, D<&ILibraryAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
+ {1000, D<&ILibraryAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ILibraryAppletProxy::~ILibraryAppletProxy() = default;
+
+Result ILibraryAppletProxy::GetAudioController(
+ Out<SharedPointer<IAudioController>> out_audio_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_audio_controller = std::make_shared<IAudioController>(system);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetDisplayController(
+ Out<SharedPointer<IDisplayController>> out_display_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetDebugFunctions(
+ Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_debug_functions = std::make_shared<IDebugFunctions>(system);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetWindowController(
+ Out<SharedPointer<IWindowController>> out_window_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
+ R_SUCCEED();
+}
+
+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);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetCommonStateGetter(
+ Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(
+ Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_library_applet_self_accessor =
+ std::make_shared<ILibraryAppletSelfAccessor>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetAppletCommonFunctions(
+ Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetHomeMenuFunctions(
+ Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletProxy::GetGlobalStateController(
+ Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_global_state_controller = std::make_shared<IGlobalStateController>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h
new file mode 100644
index 000000000..7d0714b85
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_proxy.h
@@ -0,0 +1,54 @@
+// 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::AM {
+
+struct Applet;
+class IAppletCommonFunctions;
+class IAudioController;
+class ICommonStateGetter;
+class IDebugFunctions;
+class IDisplayController;
+class IHomeMenuFunctions;
+class IGlobalStateController;
+class ILibraryAppletCreator;
+class ILibraryAppletSelfAccessor;
+class IProcessWindingController;
+class ISelfController;
+class IWindowController;
+
+class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
+public:
+ explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
+ Kernel::KProcess* process);
+ ~ILibraryAppletProxy();
+
+private:
+ Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
+ Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
+ Result GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
+ Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
+ Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
+ Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
+ Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
+ Result GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
+ Result OpenLibraryAppletSelfAccessor(
+ Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor);
+ Result GetAppletCommonFunctions(
+ Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
+ Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
+ Result GetGlobalStateController(
+ Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
+
+ Kernel::KProcess* const m_process;
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
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
new file mode 100644
index 000000000..330eb26f0
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp
@@ -0,0 +1,325 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core_timing.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/am/applet_data_broker.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/service/library_applet_self_accessor.h"
+#include "core/hle/service/am/service/storage.h"
+#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/application_manager_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::AM {
+
+namespace {
+
+AppletIdentityInfo GetCallerIdentity(Applet& applet) {
+ if (const auto caller_applet = applet.caller_applet.lock(); caller_applet) {
+ // TODO: is this actually the application ID?
+ return {
+ .applet_id = caller_applet->applet_id,
+ .application_id = caller_applet->program_id,
+ };
+ } else {
+ return {
+ .applet_id = AppletId::QLaunch,
+ .application_id = 0x0100000000001000ull,
+ };
+ }
+}
+
+} // namespace
+
+ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
+ std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)},
+ m_broker{m_applet->caller_applet_broker} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"},
+ {1, D<&ILibraryAppletSelfAccessor::PushOutData>, "PushOutData"},
+ {2, D<&ILibraryAppletSelfAccessor::PopInteractiveInData>, "PopInteractiveInData"},
+ {3, D<&ILibraryAppletSelfAccessor::PushInteractiveOutData>, "PushInteractiveOutData"},
+ {5, D<&ILibraryAppletSelfAccessor::GetPopInDataEvent>, "GetPopInDataEvent"},
+ {6, D<&ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent>, "GetPopInteractiveInDataEvent"},
+ {10, D<&ILibraryAppletSelfAccessor::ExitProcessAndReturn>, "ExitProcessAndReturn"},
+ {11, D<&ILibraryAppletSelfAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
+ {12, D<&ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo>, "GetMainAppletIdentityInfo"},
+ {13, D<&ILibraryAppletSelfAccessor::CanUseApplicationCore>, "CanUseApplicationCore"},
+ {14, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo>, "GetCallerAppletIdentityInfo"},
+ {15, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty>, "GetMainAppletApplicationControlProperty"},
+ {16, D<&ILibraryAppletSelfAccessor::GetMainAppletStorageId>, "GetMainAppletStorageId"},
+ {17, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack>, "GetCallerAppletIdentityInfoStack"},
+ {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
+ {19, D<&ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout>, "GetDesirableKeyboardLayout"},
+ {20, nullptr, "PopExtraStorage"},
+ {25, nullptr, "GetPopExtraStorageEvent"},
+ {30, nullptr, "UnpopInData"},
+ {31, nullptr, "UnpopExtraStorage"},
+ {40, nullptr, "GetIndirectLayerProducerHandle"},
+ {50, D<&ILibraryAppletSelfAccessor::ReportVisibleError>, "ReportVisibleError"},
+ {51, D<&ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext>, "ReportVisibleErrorWithErrorContext"},
+ {60, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage>, "GetMainAppletApplicationDesiredLanguage"},
+ {70, D<&ILibraryAppletSelfAccessor::GetCurrentApplicationId>, "GetCurrentApplicationId"},
+ {80, nullptr, "RequestExitToSelf"},
+ {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
+ {100, nullptr, "CreateGameMovieTrimmer"},
+ {101, nullptr, "ReserveResourceForMovieOperation"},
+ {102, nullptr, "UnreserveResourceForMovieOperation"},
+ {110, D<&ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers>, "GetMainAppletAvailableUsers"},
+ {120, nullptr, "GetLaunchStorageInfoForDebug"},
+ {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
+ {140, nullptr, "SetApplicationMemoryReservation"},
+ {150, D<&ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually>, "ShouldSetGpuTimeSliceManually"},
+ {160, D<&ILibraryAppletSelfAccessor::Cmd160>, "Cmd160"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+}
+
+ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
+
+Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) {
+ LOG_INFO(Service_AM, "called");
+ R_RETURN(m_broker->GetInData().Pop(out_storage));
+}
+
+Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) {
+ LOG_INFO(Service_AM, "called");
+ m_broker->GetOutData().Push(storage);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) {
+ LOG_INFO(Service_AM, "called");
+ R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage));
+}
+
+Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) {
+ LOG_INFO(Service_AM, "called");
+ m_broker->GetInteractiveOutData().Push(storage);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetPopInDataEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_AM, "called");
+ *out_event = m_broker->GetInData().GetEvent();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_AM, "called");
+ *out_event = m_broker->GetInteractiveInData().GetEvent();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetLibraryAppletInfo(
+ Out<LibraryAppletInfo> out_library_applet_info) {
+ LOG_INFO(Service_AM, "called");
+ *out_library_applet_info = {
+ .applet_id = m_applet->applet_id,
+ .library_applet_mode = m_applet->library_applet_mode,
+ };
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(
+ Out<AppletIdentityInfo> out_identity_info) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_identity_info = {
+ .applet_id = AppletId::QLaunch,
+ .application_id = 0x0100000000001000ull,
+ };
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::CanUseApplicationCore(Out<bool> out_can_use_application_core) {
+ // TODO: This appears to read the NPDM from state and check the core mask of the applet.
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_can_use_application_core = false;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty(
+ OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ // TODO: this should be the main applet, not the caller applet
+ const auto application = GetCallerIdentity(*m_applet);
+ std::vector<u8> nacp;
+ const auto result =
+ system.GetARPManager().GetControlProperty(&nacp, application.application_id);
+
+ if (R_SUCCEEDED(result)) {
+ std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size()));
+ }
+
+ R_RETURN(result);
+}
+
+Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id) {
+ LOG_INFO(Service_AM, "(STUBBED) called");
+ *out_storage_id = FileSys::StorageId::NandUser;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
+ LOG_INFO(Service_AM, "called");
+ system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
+ m_broker->SignalCompletion();
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(
+ Out<AppletIdentityInfo> out_identity_info) {
+ LOG_INFO(Service_AM, "called");
+ *out_identity_info = GetCallerIdentity(*m_applet);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack(
+ Out<s32> out_count, OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info) {
+ LOG_INFO(Service_AM, "called");
+
+ std::shared_ptr<Applet> applet = m_applet;
+ *out_count = 0;
+
+ do {
+ if (*out_count >= static_cast<s32>(out_identity_info.size())) {
+ break;
+ }
+ out_identity_info[(*out_count)++] = GetCallerIdentity(*applet);
+ } while ((applet = applet->caller_applet.lock()));
+
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(Out<u32> out_desirable_layout) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_desirable_layout = 0;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::ReportVisibleError(ErrorCode error_code) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
+ error_code.number);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext(
+ ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
+ error_code.number);
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
+ Out<u64> out_desired_language) {
+ // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
+ // FIXME: all of this stuff belongs to ns
+ auto identity = GetCallerIdentity(*m_applet);
+
+ // TODO(bunnei): This should be configurable
+ LOG_DEBUG(Service_AM, "called");
+
+ // Get supported languages from NACP, if possible
+ // Default to 0 (all languages supported)
+ u32 supported_languages = 0;
+
+ const auto res = [this, identity] {
+ const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ auto metadata = pm.GetControlMetadata();
+ if (metadata.first != nullptr) {
+ return metadata;
+ }
+
+ const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
+ system.GetFileSystemController(),
+ system.GetContentProvider()};
+ return pm_update.GetControlMetadata();
+ }();
+
+ if (res.first != nullptr) {
+ supported_languages = res.first->GetSupportedLanguages();
+ }
+
+ // Call IApplicationManagerInterface implementation.
+ auto& service_manager = system.ServiceManager();
+ 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
+ NS::ApplicationLanguage desired_language{};
+ R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
+
+ // Convert to settings language code.
+ u64 language_code{};
+ R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language));
+
+ LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
+
+ *out_desired_language = language_code;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_application_id) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ // TODO: this should be the main applet, not the caller applet
+ const auto main_applet = GetCallerIdentity(*m_applet);
+ *out_application_id = main_applet.application_id;
+
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
+ 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_can_select_any_user = false;
+ *out_users_count = -1;
+
+ LOG_INFO(Service_AM, "called");
+
+ if (manager.GetUserCount() > 0) {
+ *out_can_select_any_user = true;
+ *out_users_count = static_cast<s32>(manager.GetUserCount());
+
+ const auto users = manager.GetAllUsers();
+ for (size_t i = 0; i < users.size() && i < out_users.size(); i++) {
+ out_users[i] = users[i];
+ }
+ }
+
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(
+ Out<bool> out_should_set_gpu_time_slice_manually) {
+ LOG_INFO(Service_AM, "(STUBBED) called");
+ *out_should_set_gpu_time_slice_manually = false;
+ R_SUCCEED();
+}
+
+Result ILibraryAppletSelfAccessor::Cmd160(Out<u64> out_unknown0) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_unknown0 = 0;
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
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
new file mode 100644
index 000000000..3e60393c2
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.h
@@ -0,0 +1,83 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/uuid.h"
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace FileSys {
+enum class StorageId : u8;
+}
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::AM {
+
+class AppletDataBroker;
+struct Applet;
+class IStorage;
+
+struct LibraryAppletInfo {
+ AppletId applet_id;
+ LibraryAppletMode library_applet_mode;
+};
+static_assert(sizeof(LibraryAppletInfo) == 0x8, "LibraryAppletInfo has incorrect size.");
+
+struct ErrorCode {
+ u32 category;
+ u32 number;
+};
+static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
+
+struct ErrorContext {
+ u8 type;
+ INSERT_PADDING_BYTES_NOINIT(0x7);
+ std::array<u8, 0x1f4> data;
+ Result result;
+};
+static_assert(sizeof(ErrorContext) == 0x200, "ErrorContext has incorrect size.");
+
+class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
+public:
+ explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~ILibraryAppletSelfAccessor() override;
+
+private:
+ Result PopInData(Out<SharedPointer<IStorage>> out_storage);
+ Result PushOutData(SharedPointer<IStorage> storage);
+ Result PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage);
+ Result PushInteractiveOutData(SharedPointer<IStorage> storage);
+ Result GetPopInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetPopInteractiveInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetLibraryAppletInfo(Out<LibraryAppletInfo> out_library_applet_info);
+ Result GetMainAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
+ Result CanUseApplicationCore(Out<bool> out_can_use_application_core);
+ Result GetMainAppletApplicationControlProperty(
+ OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp);
+ Result GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id);
+ Result ExitProcessAndReturn();
+ Result GetCallerAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
+ Result GetCallerAppletIdentityInfoStack(
+ Out<s32> out_count,
+ OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info);
+ Result GetDesirableKeyboardLayout(Out<u32> out_desirable_layout);
+ Result ReportVisibleError(ErrorCode error_code);
+ Result ReportVisibleErrorWithErrorContext(
+ 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_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);
+
+ const std::shared_ptr<Applet> m_applet;
+ const std::shared_ptr<AppletDataBroker> m_broker;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp
new file mode 100644
index 000000000..8e556fdd6
--- /dev/null
+++ b/src/core/hle/service/am/service/lock_accessor.cpp
@@ -0,0 +1,75 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/lock_accessor.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+ILockAccessor::ILockAccessor(Core::System& system_)
+ : ServiceFramework{system_, "ILockAccessor"}, m_context{system_, "ILockAccessor"},
+ m_event{m_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, D<&ILockAccessor::TryLock>, "TryLock"},
+ {2, D<&ILockAccessor::Unlock>, "Unlock"},
+ {3, D<&ILockAccessor::GetEvent>, "GetEvent"},
+ {4, D<&ILockAccessor::IsLocked>, "IsLocked"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ m_event.Signal();
+}
+
+ILockAccessor::~ILockAccessor() = default;
+
+Result ILockAccessor::TryLock(Out<bool> out_is_locked,
+ OutCopyHandle<Kernel::KReadableEvent> out_handle,
+ bool return_handle) {
+ LOG_INFO(Service_AM, "called, return_handle={}", return_handle);
+
+ {
+ std::scoped_lock lk{m_mutex};
+ if (m_is_locked) {
+ *out_is_locked = false;
+ } else {
+ m_is_locked = true;
+ *out_is_locked = true;
+ }
+ }
+
+ if (return_handle) {
+ *out_handle = m_event.GetHandle();
+ }
+
+ R_SUCCEED();
+}
+
+Result ILockAccessor::Unlock() {
+ LOG_INFO(Service_AM, "called");
+
+ {
+ std::scoped_lock lk{m_mutex};
+ m_is_locked = false;
+ }
+
+ m_event.Signal();
+ R_SUCCEED();
+}
+
+Result ILockAccessor::GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle) {
+ LOG_INFO(Service_AM, "called");
+ *out_handle = m_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result ILockAccessor::IsLocked(Out<bool> out_is_locked) {
+ LOG_INFO(Service_AM, "called");
+ std::scoped_lock lk{m_mutex};
+ *out_is_locked = m_is_locked;
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/lock_accessor.h b/src/core/hle/service/am/service/lock_accessor.h
new file mode 100644
index 000000000..9bfb5c050
--- /dev/null
+++ b/src/core/hle/service/am/service/lock_accessor.h
@@ -0,0 +1,32 @@
+// 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/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILockAccessor final : public ServiceFramework<ILockAccessor> {
+public:
+ explicit ILockAccessor(Core::System& system_);
+ ~ILockAccessor() override;
+
+private:
+ Result TryLock(Out<bool> out_is_locked, OutCopyHandle<Kernel::KReadableEvent> out_handle,
+ bool return_handle);
+ Result Unlock();
+ Result GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle);
+ Result IsLocked(Out<bool> out_is_locked);
+
+private:
+ KernelHelpers::ServiceContext m_context;
+ Event m_event;
+ std::mutex m_mutex{};
+ bool m_is_locked{};
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/process_winding_controller.cpp b/src/core/hle/service/am/service/process_winding_controller.cpp
new file mode 100644
index 000000000..10df830d7
--- /dev/null
+++ b/src/core/hle/service/am/service/process_winding_controller.cpp
@@ -0,0 +1,54 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/service/library_applet_accessor.h"
+#include "core/hle/service/am/service/process_winding_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IProcessWindingController::IProcessWindingController(Core::System& system_,
+ std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "IProcessWindingController"}, m_applet{std::move(applet)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"},
+ {11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"},
+ {21, nullptr, "PushContext"},
+ {22, nullptr, "PopContext"},
+ {23, nullptr, "CancelWindingReservation"},
+ {30, nullptr, "WindAndDoReserved"},
+ {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
+ {41, nullptr, "ReserveToStartAndWait"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IProcessWindingController::~IProcessWindingController() = default;
+
+Result IProcessWindingController::GetLaunchReason(
+ Out<AppletProcessLaunchReason> out_launch_reason) {
+ LOG_INFO(Service_AM, "called");
+ *out_launch_reason = m_applet->launch_reason;
+ R_SUCCEED();
+}
+
+Result IProcessWindingController::OpenCallingLibraryApplet(
+ Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet) {
+ LOG_INFO(Service_AM, "called");
+
+ const auto caller_applet = m_applet->caller_applet.lock();
+ if (caller_applet == nullptr) {
+ LOG_ERROR(Service_AM, "No caller applet available");
+ R_THROW(ResultUnknown);
+ }
+
+ *out_calling_library_applet = std::make_shared<ILibraryAppletAccessor>(
+ system, m_applet->caller_applet_broker, caller_applet);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/process_winding_controller.h b/src/core/hle/service/am/service/process_winding_controller.h
new file mode 100644
index 000000000..4408af1f1
--- /dev/null
+++ b/src/core/hle/service/am/service/process_winding_controller.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+struct Applet;
+class ILibraryAppletAccessor;
+
+class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
+public:
+ explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
+ ~IProcessWindingController() override;
+
+private:
+ Result GetLaunchReason(Out<AppletProcessLaunchReason> out_launch_reason);
+ Result OpenCallingLibraryApplet(
+ Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet);
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp
new file mode 100644
index 000000000..06314407c
--- /dev/null
+++ b/src/core/hle/service/am/service/self_controller.cpp
@@ -0,0 +1,394 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/result.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/service/self_controller.h"
+#include "core/hle/service/caps/caps_su.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/vi_results.h"
+
+namespace Service::AM {
+
+ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> 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"},
+ {1, D<&ISelfController::LockExit>, "LockExit"},
+ {2, D<&ISelfController::UnlockExit>, "UnlockExit"},
+ {3, D<&ISelfController::EnterFatalSection>, "EnterFatalSection"},
+ {4, D<&ISelfController::LeaveFatalSection>, "LeaveFatalSection"},
+ {9, D<&ISelfController::GetLibraryAppletLaunchableEvent>, "GetLibraryAppletLaunchableEvent"},
+ {10, D<&ISelfController::SetScreenShotPermission>, "SetScreenShotPermission"},
+ {11, D<&ISelfController::SetOperationModeChangedNotification>, "SetOperationModeChangedNotification"},
+ {12, D<&ISelfController::SetPerformanceModeChangedNotification>, "SetPerformanceModeChangedNotification"},
+ {13, D<&ISelfController::SetFocusHandlingMode>, "SetFocusHandlingMode"},
+ {14, D<&ISelfController::SetRestartMessageEnabled>, "SetRestartMessageEnabled"},
+ {15, D<&ISelfController::SetScreenShotAppletIdentityInfo>, "SetScreenShotAppletIdentityInfo"},
+ {16, D<&ISelfController::SetOutOfFocusSuspendingEnabled>, "SetOutOfFocusSuspendingEnabled"},
+ {17, nullptr, "SetControllerFirmwareUpdateSection"},
+ {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
+ {19, D<&ISelfController::SetAlbumImageOrientation>, "SetAlbumImageOrientation"},
+ {20, nullptr, "SetDesirableKeyboardLayout"},
+ {21, nullptr, "GetScreenShotProgramId"},
+ {40, D<&ISelfController::CreateManagedDisplayLayer>, "CreateManagedDisplayLayer"},
+ {41, D<&ISelfController::IsSystemBufferSharingEnabled>, "IsSystemBufferSharingEnabled"},
+ {42, D<&ISelfController::GetSystemSharedLayerHandle>, "GetSystemSharedLayerHandle"},
+ {43, D<&ISelfController::GetSystemSharedBufferHandle>, "GetSystemSharedBufferHandle"},
+ {44, D<&ISelfController::CreateManagedDisplaySeparableLayer>, "CreateManagedDisplaySeparableLayer"},
+ {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
+ {46, nullptr, "SetRecordingLayerCompositionEnabled"},
+ {50, D<&ISelfController::SetHandlesRequestToDisplay>, "SetHandlesRequestToDisplay"},
+ {51, D<&ISelfController::ApproveToDisplay>, "ApproveToDisplay"},
+ {60, D<&ISelfController::OverrideAutoSleepTimeAndDimmingTime>, "OverrideAutoSleepTimeAndDimmingTime"},
+ {61, D<&ISelfController::SetMediaPlaybackState>, "SetMediaPlaybackState"},
+ {62, D<&ISelfController::SetIdleTimeDetectionExtension>, "SetIdleTimeDetectionExtension"},
+ {63, D<&ISelfController::GetIdleTimeDetectionExtension>, "GetIdleTimeDetectionExtension"},
+ {64, nullptr, "SetInputDetectionSourceSet"},
+ {65, D<&ISelfController::ReportUserIsActive>, "ReportUserIsActive"},
+ {66, nullptr, "GetCurrentIlluminance"},
+ {67, nullptr, "IsIlluminanceAvailable"},
+ {68, D<&ISelfController::SetAutoSleepDisabled>, "SetAutoSleepDisabled"},
+ {69, D<&ISelfController::IsAutoSleepDisabled>, "IsAutoSleepDisabled"},
+ {70, nullptr, "ReportMultimediaError"},
+ {71, nullptr, "GetCurrentIlluminanceEx"},
+ {72, D<&ISelfController::SetInputDetectionPolicy>, "SetInputDetectionPolicy"},
+ {80, nullptr, "SetWirelessPriorityMode"},
+ {90, D<&ISelfController::GetAccumulatedSuspendedTickValue>, "GetAccumulatedSuspendedTickValue"},
+ {91, D<&ISelfController::GetAccumulatedSuspendedTickChangedEvent>, "GetAccumulatedSuspendedTickChangedEvent"},
+ {100, D<&ISelfController::SetAlbumImageTakenNotificationEnabled>, "SetAlbumImageTakenNotificationEnabled"},
+ {110, nullptr, "SetApplicationAlbumUserData"},
+ {120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"},
+ {130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"},
+ {1000, nullptr, "GetDebugStorageChannel"},
+ };
+ // 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() {
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->display_layer_manager.Finalize();
+}
+
+Result ISelfController::Exit() {
+ LOG_DEBUG(Service_AM, "called");
+
+ // TODO
+ system.Exit();
+
+ R_SUCCEED();
+}
+
+Result ISelfController::LockExit() {
+ LOG_DEBUG(Service_AM, "called");
+
+ system.SetExitLocked(true);
+
+ R_SUCCEED();
+}
+
+Result ISelfController::UnlockExit() {
+ LOG_DEBUG(Service_AM, "called");
+
+ system.SetExitLocked(false);
+
+ if (system.GetExitRequested()) {
+ system.Exit();
+ }
+
+ R_SUCCEED();
+}
+
+Result ISelfController::EnterFatalSection() {
+ std::scoped_lock lk{m_applet->lock};
+
+ m_applet->fatal_section_count++;
+ LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", m_applet->fatal_section_count);
+
+ R_SUCCEED();
+}
+
+Result ISelfController::LeaveFatalSection() {
+ LOG_DEBUG(Service_AM, "called");
+
+ // Entry and exit of fatal sections must be balanced.
+ std::scoped_lock lk{m_applet->lock};
+ R_UNLESS(m_applet->fatal_section_count > 0, AM::ResultFatalSectionCountImbalance);
+ m_applet->fatal_section_count--;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::GetLibraryAppletLaunchableEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ m_applet->library_applet_launchable_event.Signal();
+ *out_event = m_applet->library_applet_launchable_event.GetHandle();
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetScreenShotPermission(ScreenshotPermission screen_shot_permission) {
+ LOG_DEBUG(Service_AM, "called, permission={}", screen_shot_permission);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->screenshot_permission = screen_shot_permission;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetOperationModeChangedNotification(bool enabled) {
+ LOG_INFO(Service_AM, "called, enabled={}", enabled);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->operation_mode_changed_notification_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) {
+ LOG_INFO(Service_AM, "called, enabled={}", enabled);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->performance_mode_changed_notification_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify,
+ background, suspend);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->focus_handling_mode = {notify, background, suspend};
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetRestartMessageEnabled(bool enabled) {
+ LOG_INFO(Service_AM, "called, enabled={}", enabled);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->restart_message_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetScreenShotAppletIdentityInfo(
+ AppletIdentityInfo screen_shot_applet_identity_info) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->screen_shot_identity = screen_shot_applet_identity_info;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) {
+ LOG_INFO(Service_AM, "called, enabled={}", enabled);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->out_of_focus_suspension_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetAlbumImageOrientation(
+ Capture::AlbumImageOrientation album_image_orientation) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", album_image_orientation);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->album_image_orientation = album_image_orientation;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::IsSystemBufferSharingEnabled() {
+ LOG_INFO(Service_AM, "called");
+
+ std::scoped_lock lk{m_applet->lock};
+ R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled());
+}
+
+Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) {
+ LOG_INFO(Service_AM, "called");
+
+ u64 layer_id;
+
+ 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, "called");
+
+ 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");
+
+ 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");
+
+ 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) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, enable={}", enable);
+ R_SUCCEED();
+}
+
+Result ISelfController::ApproveToDisplay() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ISelfController::SetMediaPlaybackState(bool state) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
+ R_SUCCEED();
+}
+
+Result ISelfController::OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, a={}, b={}, c={}, d={}", a, b, c, d);
+ R_SUCCEED();
+}
+
+Result ISelfController::SetIdleTimeDetectionExtension(
+ IdleTimeDetectionExtension idle_time_detection_extension) {
+ LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", idle_time_detection_extension);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->idle_time_detection_extension = idle_time_detection_extension;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::GetIdleTimeDetectionExtension(
+ Out<IdleTimeDetectionExtension> out_idle_time_detection_extension) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ std::scoped_lock lk{m_applet->lock};
+ *out_idle_time_detection_extension = m_applet->idle_time_detection_extension;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::ReportUserIsActive() {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ISelfController::SetAutoSleepDisabled(bool is_auto_sleep_disabled) {
+ LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
+
+ // On the system itself, if the previous state of is_auto_sleep_disabled
+ // differed from the current value passed in, it'd signify the internal
+ // window manager to update (and also increment some statistics like update counts)
+ //
+ // It'd also indicate this change to an idle handling context.
+ //
+ // However, given we're emulating this behavior, most of this can be ignored
+ // and it's sufficient to simply set the member variable for querying via
+ // IsAutoSleepDisabled().
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->auto_sleep_disabled = is_auto_sleep_disabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled) {
+ LOG_DEBUG(Service_AM, "called.");
+
+ std::scoped_lock lk{m_applet->lock};
+ *out_is_auto_sleep_disabled = m_applet->auto_sleep_disabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result ISelfController::GetAccumulatedSuspendedTickValue(
+ Out<u64> out_accumulated_suspended_tick_value) {
+ LOG_DEBUG(Service_AM, "called.");
+
+ // This command returns the total number of system ticks since ISelfController creation
+ // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
+ // can just always return 0 ticks.
+ std::scoped_lock lk{m_applet->lock};
+ *out_accumulated_suspended_tick_value = m_applet->suspended_ticks;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::GetAccumulatedSuspendedTickChangedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_AM, "called.");
+
+ *out_event = m_applet->accumulated_suspended_tick_changed_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result ISelfController::SetAlbumImageTakenNotificationEnabled(bool enabled) {
+ LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
+
+ // This service call sets an internal flag whether a notification is shown when an image is
+ // captured. Currently we do not support capturing images via the capture button, so this can be
+ // stubbed for now.
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->album_image_taken_notification_enabled = enabled;
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option) {
+ LOG_INFO(Service_AM, "called, report_option={}", album_report_option);
+
+ const auto screenshot_service =
+ system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
+ "caps:su");
+
+ if (screenshot_service) {
+ screenshot_service->CaptureAndSaveScreenshot(album_report_option);
+ }
+
+ R_SUCCEED();
+}
+
+Result ISelfController::SetRecordVolumeMuted(bool muted) {
+ LOG_WARNING(Service_AM, "(STUBBED) called. muted={}", muted);
+
+ std::scoped_lock lk{m_applet->lock};
+ m_applet->record_volume_muted = muted;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h
new file mode 100644
index 000000000..eca083cfe
--- /dev/null
+++ b/src/core/hle/service/am/service/self_controller.h
@@ -0,0 +1,71 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/am_types.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Capture {
+enum class AlbumImageOrientation;
+enum class AlbumReportOption;
+} // namespace Service::Capture
+
+namespace Service::AM {
+
+struct Applet;
+
+class ISelfController final : public ServiceFramework<ISelfController> {
+public:
+ explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
+ Kernel::KProcess* process);
+ ~ISelfController() override;
+
+private:
+ Result Exit();
+ Result LockExit();
+ Result UnlockExit();
+ Result EnterFatalSection();
+ Result LeaveFatalSection();
+ Result GetLibraryAppletLaunchableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result SetScreenShotPermission(ScreenshotPermission screen_shot_permission);
+ Result SetOperationModeChangedNotification(bool enabled);
+ Result SetPerformanceModeChangedNotification(bool enabled);
+ Result SetFocusHandlingMode(bool notify, bool background, bool suspend);
+ Result SetRestartMessageEnabled(bool enabled);
+ Result SetScreenShotAppletIdentityInfo(AppletIdentityInfo screen_shot_applet_identity_info);
+ Result SetOutOfFocusSuspendingEnabled(bool enabled);
+ Result SetAlbumImageOrientation(Capture::AlbumImageOrientation album_image_orientation);
+ Result IsSystemBufferSharingEnabled();
+ Result GetSystemSharedBufferHandle(Out<u64> out_buffer_id);
+ Result GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id);
+ Result CreateManagedDisplayLayer(Out<u64> out_layer_id);
+ Result CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
+ Out<u64> out_recording_layer_id);
+ Result SetHandlesRequestToDisplay(bool enable);
+ Result ApproveToDisplay();
+ Result SetMediaPlaybackState(bool state);
+ Result OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d);
+ Result SetIdleTimeDetectionExtension(IdleTimeDetectionExtension idle_time_detection_extension);
+ Result GetIdleTimeDetectionExtension(
+ Out<IdleTimeDetectionExtension> out_idle_time_detection_extension);
+ Result ReportUserIsActive();
+ Result SetAutoSleepDisabled(bool is_auto_sleep_disabled);
+ Result IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled);
+ Result SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy);
+ Result GetAccumulatedSuspendedTickValue(Out<u64> out_accumulated_suspended_tick_value);
+ Result GetAccumulatedSuspendedTickChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result SetAlbumImageTakenNotificationEnabled(bool enabled);
+ Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
+ Result SetRecordVolumeMuted(bool muted);
+
+ Kernel::KProcess* const m_process;
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage.cpp b/src/core/hle/service/am/service/storage.cpp
new file mode 100644
index 000000000..25ee0afbd
--- /dev/null
+++ b/src/core/hle/service/am/service/storage.cpp
@@ -0,0 +1,48 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/library_applet_storage.h"
+#include "core/hle/service/am/service/storage.h"
+#include "core/hle/service/am/service/storage_accessor.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl)
+ : ServiceFramework{system_, "IStorage"}, m_impl{std::move(impl)} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IStorage::Open>, "Open"},
+ {1, D<&IStorage::OpenTransferStorage>, "OpenTransferStorage"},
+ };
+
+ RegisterHandlers(functions);
+}
+
+IStorage::IStorage(Core::System& system_, std::vector<u8>&& data)
+ : IStorage(system_, CreateStorage(std::move(data))) {}
+
+IStorage::~IStorage() = default;
+
+Result IStorage::Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor) {
+ LOG_DEBUG(Service_AM, "called");
+
+ R_UNLESS(m_impl->GetHandle() == nullptr, AM::ResultInvalidStorageType);
+
+ *out_storage_accessor = std::make_shared<IStorageAccessor>(system, m_impl);
+ R_SUCCEED();
+}
+
+Result IStorage::OpenTransferStorage(
+ Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor) {
+ R_UNLESS(m_impl->GetHandle() != nullptr, AM::ResultInvalidStorageType);
+
+ *out_transfer_storage_accessor = std::make_shared<ITransferStorageAccessor>(system, m_impl);
+ R_SUCCEED();
+}
+
+std::vector<u8> IStorage::GetData() const {
+ return m_impl->GetData();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage.h b/src/core/hle/service/am/service/storage.h
new file mode 100644
index 000000000..cde2ed0ea
--- /dev/null
+++ b/src/core/hle/service/am/service/storage.h
@@ -0,0 +1,35 @@
+// 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::AM {
+
+class LibraryAppletStorage;
+class IStorageAccessor;
+class ITransferStorageAccessor;
+
+class IStorage final : public ServiceFramework<IStorage> {
+public:
+ explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
+ explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
+ ~IStorage() override;
+
+ std::shared_ptr<LibraryAppletStorage> GetImpl() const {
+ return m_impl;
+ }
+
+ std::vector<u8> GetData() const;
+
+private:
+ Result Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor);
+ Result OpenTransferStorage(
+ Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor);
+
+ const std::shared_ptr<LibraryAppletStorage> m_impl;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage_accessor.cpp b/src/core/hle/service/am/service/storage_accessor.cpp
new file mode 100644
index 000000000..84577fee4
--- /dev/null
+++ b/src/core/hle/service/am/service/storage_accessor.cpp
@@ -0,0 +1,68 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/am/library_applet_storage.h"
+#include "core/hle/service/am/service/storage_accessor.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IStorageAccessor::IStorageAccessor(Core::System& system_,
+ std::shared_ptr<LibraryAppletStorage> impl)
+ : ServiceFramework{system_, "IStorageAccessor"}, m_impl{std::move(impl)} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IStorageAccessor::GetSize>, "GetSize"},
+ {10, D<&IStorageAccessor::Write>, "Write"},
+ {11, D<&IStorageAccessor::Read>, "Read"},
+ };
+
+ RegisterHandlers(functions);
+}
+
+IStorageAccessor::~IStorageAccessor() = default;
+
+Result IStorageAccessor::GetSize(Out<s64> out_size) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_size = m_impl->GetSize();
+ R_SUCCEED();
+}
+
+Result IStorageAccessor::Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset) {
+ LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, buffer.size());
+ R_RETURN(m_impl->Write(offset, buffer.data(), buffer.size()));
+}
+
+Result IStorageAccessor::Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset) {
+ LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, out_buffer.size());
+ R_RETURN(m_impl->Read(offset, out_buffer.data(), out_buffer.size()));
+}
+
+ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_,
+ std::shared_ptr<LibraryAppletStorage> impl)
+ : ServiceFramework{system_, "ITransferStorageAccessor"}, m_impl{std::move(impl)} {
+ static const FunctionInfo functions[] = {
+ {0, D<&ITransferStorageAccessor::GetSize>, "GetSize"},
+ {1, D<&ITransferStorageAccessor::GetHandle>, "GetHandle"},
+ };
+
+ RegisterHandlers(functions);
+}
+
+ITransferStorageAccessor::~ITransferStorageAccessor() = default;
+
+Result ITransferStorageAccessor::GetSize(Out<s64> out_size) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_size = m_impl->GetSize();
+ R_SUCCEED();
+}
+
+Result ITransferStorageAccessor::GetHandle(Out<s64> out_size,
+ OutCopyHandle<Kernel::KTransferMemory> out_handle) {
+ LOG_INFO(Service_AM, "called");
+ *out_size = m_impl->GetSize();
+ *out_handle = m_impl->GetHandle();
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage_accessor.h b/src/core/hle/service/am/service/storage_accessor.h
new file mode 100644
index 000000000..1a01730e0
--- /dev/null
+++ b/src/core/hle/service/am/service/storage_accessor.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/am/library_applet_storage.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
+public:
+ explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
+ ~IStorageAccessor() override;
+
+private:
+ Result GetSize(Out<s64> out_size);
+ Result Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset);
+ Result Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset);
+
+ const std::shared_ptr<LibraryAppletStorage> m_impl;
+};
+
+class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> {
+public:
+ explicit ITransferStorageAccessor(Core::System& system_,
+ std::shared_ptr<LibraryAppletStorage> impl);
+ ~ITransferStorageAccessor() override;
+
+private:
+ Result GetSize(Out<s64> out_size);
+ Result GetHandle(Out<s64> out_size, OutCopyHandle<Kernel::KTransferMemory> out_handle);
+
+ const std::shared_ptr<LibraryAppletStorage> m_impl;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp
new file mode 100644
index 000000000..d1871ef9b
--- /dev/null
+++ b/src/core/hle/service/am/service/system_applet_proxy.cpp
@@ -0,0 +1,131 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/service/applet_common_functions.h"
+#include "core/hle/service/am/service/application_creator.h"
+#include "core/hle/service/am/service/audio_controller.h"
+#include "core/hle/service/am/service/common_state_getter.h"
+#include "core/hle/service/am/service/debug_functions.h"
+#include "core/hle/service/am/service/display_controller.h"
+#include "core/hle/service/am/service/global_state_controller.h"
+#include "core/hle/service/am/service/home_menu_functions.h"
+#include "core/hle/service/am/service/library_applet_creator.h"
+#include "core/hle/service/am/service/process_winding_controller.h"
+#include "core/hle/service/am/service/self_controller.h"
+#include "core/hle/service/am/service/system_applet_proxy.h"
+#include "core/hle/service/am/service/window_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> 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"},
+ {1, D<&ISystemAppletProxy::GetSelfController>, "GetSelfController"},
+ {2, D<&ISystemAppletProxy::GetWindowController>, "GetWindowController"},
+ {3, D<&ISystemAppletProxy::GetAudioController>, "GetAudioController"},
+ {4, D<&ISystemAppletProxy::GetDisplayController>, "GetDisplayController"},
+ {10, D<&ISystemAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
+ {11, D<&ISystemAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
+ {20, D<&ISystemAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
+ {21, D<&ISystemAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
+ {22, D<&ISystemAppletProxy::GetApplicationCreator>, "GetApplicationCreator"},
+ {23, D<&ISystemAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
+ {1000, D<&ISystemAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemAppletProxy::~ISystemAppletProxy() = default;
+
+Result ISystemAppletProxy::GetAudioController(
+ Out<SharedPointer<IAudioController>> out_audio_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_audio_controller = std::make_shared<IAudioController>(system);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetDisplayController(
+ Out<SharedPointer<IDisplayController>> out_display_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetDebugFunctions(
+ Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_debug_functions = std::make_shared<IDebugFunctions>(system);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetWindowController(
+ Out<SharedPointer<IWindowController>> out_window_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
+ R_SUCCEED();
+}
+
+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);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetCommonStateGetter(
+ Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetApplicationCreator(
+ Out<SharedPointer<IApplicationCreator>> out_application_creator) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_application_creator = std::make_shared<IApplicationCreator>(system);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetAppletCommonFunctions(
+ Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetHomeMenuFunctions(
+ Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
+ R_SUCCEED();
+}
+
+Result ISystemAppletProxy::GetGlobalStateController(
+ Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
+ LOG_DEBUG(Service_AM, "called");
+ *out_global_state_controller = std::make_shared<IGlobalStateController>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h
new file mode 100644
index 000000000..67cd50e03
--- /dev/null
+++ b/src/core/hle/service/am/service/system_applet_proxy.h
@@ -0,0 +1,53 @@
+// 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::AM {
+
+struct Applet;
+class IAppletCommonFunctions;
+class IApplicationCreator;
+class IAudioController;
+class ICommonStateGetter;
+class IDebugFunctions;
+class IDisplayController;
+class IHomeMenuFunctions;
+class IGlobalStateController;
+class ILibraryAppletCreator;
+class IProcessWindingController;
+class ISelfController;
+class IWindowController;
+
+class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
+public:
+ explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
+ Kernel::KProcess* process);
+ ~ISystemAppletProxy();
+
+private:
+ Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
+ Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
+ Result GetProcessWindingController(
+ Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
+ Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
+ Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
+ Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
+ Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
+ Result GetLibraryAppletCreator(
+ Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
+ Result GetApplicationCreator(Out<SharedPointer<IApplicationCreator>> out_application_creator);
+ Result GetAppletCommonFunctions(
+ Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
+ Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
+ Result GetGlobalStateController(
+ Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
+
+ Kernel::KProcess* const m_process;
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp
new file mode 100644
index 000000000..99a4f50a2
--- /dev/null
+++ b/src/core/hle/service/am/service/window_controller.cpp
@@ -0,0 +1,86 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet.h"
+#include "core/hle/service/am/applet_manager.h"
+#include "core/hle/service/am/service/window_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::AM {
+
+IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet)
+ : ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateWindow"},
+ {1, D<&IWindowController::GetAppletResourceUserId>, "GetAppletResourceUserId"},
+ {2, D<&IWindowController::GetAppletResourceUserIdOfCallerApplet>, "GetAppletResourceUserIdOfCallerApplet"},
+ {10, D<&IWindowController::AcquireForegroundRights>, "AcquireForegroundRights"},
+ {11, D<&IWindowController::ReleaseForegroundRights>, "ReleaseForegroundRights"},
+ {12, D<&IWindowController::RejectToChangeIntoBackground>, "RejectToChangeIntoBackground"},
+ {20, D<&IWindowController::SetAppletWindowVisibility>, "SetAppletWindowVisibility"},
+ {21, D<&IWindowController::SetAppletGpuTimeSlice>, "SetAppletGpuTimeSlice"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IWindowController::~IWindowController() = default;
+
+Result IWindowController::GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid) {
+ LOG_INFO(Service_AM, "called");
+ *out_aruid = m_applet->aruid;
+ R_SUCCEED();
+}
+
+Result IWindowController::GetAppletResourceUserIdOfCallerApplet(
+ Out<AppletResourceUserId> out_aruid) {
+ LOG_INFO(Service_AM, "called");
+
+ if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet != nullptr) {
+ *out_aruid = caller_applet->aruid;
+ } else {
+ *out_aruid = AppletResourceUserId{};
+ }
+
+ R_SUCCEED();
+}
+
+Result IWindowController::AcquireForegroundRights() {
+ LOG_INFO(Service_AM, "called");
+ R_SUCCEED();
+}
+
+Result IWindowController::ReleaseForegroundRights() {
+ LOG_INFO(Service_AM, "called");
+ R_SUCCEED();
+}
+
+Result IWindowController::RejectToChangeIntoBackground() {
+ LOG_INFO(Service_AM, "called");
+ R_SUCCEED();
+}
+
+Result IWindowController::SetAppletWindowVisibility(bool visible) {
+ m_applet->display_layer_manager.SetWindowVisibility(visible);
+ m_applet->hid_registration.EnableAppletToGetInput(visible);
+
+ if (visible) {
+ m_applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
+ m_applet->focus_state = FocusState::InFocus;
+ } else {
+ m_applet->focus_state = FocusState::NotInFocus;
+ }
+
+ m_applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
+
+ R_SUCCEED();
+}
+
+Result IWindowController::SetAppletGpuTimeSlice(s64 time_slice) {
+ LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice);
+ R_SUCCEED();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/window_controller.h b/src/core/hle/service/am/service/window_controller.h
new file mode 100644
index 000000000..bfbad9bcc
--- /dev/null
+++ b/src/core/hle/service/am/service/window_controller.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/service.h"
+
+namespace Service::AM {
+
+struct Applet;
+
+class IWindowController final : public ServiceFramework<IWindowController> {
+public:
+ explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet);
+ ~IWindowController() override;
+
+private:
+ Result GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid);
+ Result GetAppletResourceUserIdOfCallerApplet(Out<AppletResourceUserId> out_aruid);
+ Result AcquireForegroundRights();
+ Result ReleaseForegroundRights();
+ Result RejectToChangeIntoBackground();
+ Result SetAppletWindowVisibility(bool visible);
+ Result SetAppletGpuTimeSlice(s64 time_slice);
+
+ const std::shared_ptr<Applet> m_applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp
deleted file mode 100644
index ec581e32b..000000000
--- a/src/core/hle/service/am/spsm.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/spsm.h"
-
-namespace Service::AM {
-
-SPSM::SPSM(Core::System& system_) : ServiceFramework{system_, "spsm"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetState"},
- {1, nullptr, "EnterSleep"},
- {2, nullptr, "GetLastWakeReason"},
- {3, nullptr, "Shutdown"},
- {4, nullptr, "GetNotificationMessageEventHandle"},
- {5, nullptr, "ReceiveNotificationMessage"},
- {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"},
- {7, nullptr, "ResetEventLog"},
- {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"},
- {9, nullptr, "ChangeHomeButtonLongPressingTime"},
- {10, nullptr, "PutErrorState"},
- {11, nullptr, "InvalidateCurrentHomeButtonPressing"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-SPSM::~SPSM() = default;
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h
deleted file mode 100644
index 922f8863e..000000000
--- a/src/core/hle/service/am/spsm.h
+++ /dev/null
@@ -1,20 +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::AM {
-
-class SPSM final : public ServiceFramework<SPSM> {
-public:
- explicit SPSM(Core::System& system_);
- ~SPSM() override;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp
deleted file mode 100644
index 4e82afd1c..000000000
--- a/src/core/hle/service/am/storage.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/am_results.h"
-#include "core/hle/service/am/library_applet_storage.h"
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/am/storage_accessor.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_)
- : ServiceFramework{system_, "IStorage"}, impl{std::move(impl_)} {
- static const FunctionInfo functions[] = {
- {0, &IStorage::Open, "Open"},
- {1, &IStorage::OpenTransferStorage, "OpenTransferStorage"},
- };
-
- RegisterHandlers(functions);
-}
-
-IStorage::IStorage(Core::System& system_, std::vector<u8>&& data)
- : IStorage(system_, CreateStorage(std::move(data))) {}
-
-IStorage::~IStorage() = default;
-
-void IStorage::Open(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- if (impl->GetHandle() != nullptr) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultInvalidStorageType);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IStorageAccessor>(system, impl);
-}
-
-void IStorage::OpenTransferStorage(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- if (impl->GetHandle() == nullptr) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(AM::ResultInvalidStorageType);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ITransferStorageAccessor>(system, impl);
-}
-
-std::vector<u8> IStorage::GetData() const {
- return impl->GetData();
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h
deleted file mode 100644
index 10d00b141..000000000
--- a/src/core/hle/service/am/storage.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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::AM {
-
-class LibraryAppletStorage;
-
-class IStorage final : public ServiceFramework<IStorage> {
-public:
- explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_);
- explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
- ~IStorage() override;
-
- std::shared_ptr<LibraryAppletStorage> GetImpl() const {
- return impl;
- }
-
- std::vector<u8> GetData() const;
-
-private:
- void Open(HLERequestContext& ctx);
- void OpenTransferStorage(HLERequestContext& ctx);
-
- const std::shared_ptr<LibraryAppletStorage> impl;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp
deleted file mode 100644
index a1184b065..000000000
--- a/src/core/hle/service/am/storage_accessor.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/service/am/am_results.h"
-#include "core/hle/service/am/library_applet_storage.h"
-#include "core/hle/service/am/storage_accessor.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IStorageAccessor::IStorageAccessor(Core::System& system_,
- std::shared_ptr<LibraryAppletStorage> impl_)
- : ServiceFramework{system_, "IStorageAccessor"}, impl{std::move(impl_)} {
- static const FunctionInfo functions[] = {
- {0, &IStorageAccessor::GetSize, "GetSize"},
- {10, &IStorageAccessor::Write, "Write"},
- {11, &IStorageAccessor::Read, "Read"},
- };
-
- RegisterHandlers(functions);
-}
-
-IStorageAccessor::~IStorageAccessor() = default;
-
-void IStorageAccessor::GetSize(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 4};
-
- rb.Push(ResultSuccess);
- rb.Push(impl->GetSize());
-}
-
-void IStorageAccessor::Write(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const s64 offset{rp.Pop<s64>()};
- const auto data{ctx.ReadBuffer()};
- LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size());
-
- const auto res{impl->Write(offset, data.data(), data.size())};
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
-}
-
-void IStorageAccessor::Read(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const s64 offset{rp.Pop<s64>()};
- std::vector<u8> data(ctx.GetWriteBufferSize());
-
- LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size());
-
- const auto res{impl->Read(offset, data.data(), data.size())};
-
- ctx.WriteBuffer(data);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
-}
-
-ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_,
- std::shared_ptr<LibraryAppletStorage> impl_)
- : ServiceFramework{system_, "ITransferStorageAccessor"}, impl{std::move(impl_)} {
- static const FunctionInfo functions[] = {
- {0, &ITransferStorageAccessor::GetSize, "GetSize"},
- {1, &ITransferStorageAccessor::GetHandle, "GetHandle"},
- };
-
- RegisterHandlers(functions);
-}
-
-ITransferStorageAccessor::~ITransferStorageAccessor() = default;
-
-void ITransferStorageAccessor::GetSize(HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(impl->GetSize());
-}
-
-void ITransferStorageAccessor::GetHandle(HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 4, 1};
- rb.Push(ResultSuccess);
- rb.Push(impl->GetSize());
- rb.PushCopyObjects(impl->GetHandle());
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h
deleted file mode 100644
index b9aa85a66..000000000
--- a/src/core/hle/service/am/storage_accessor.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/am/storage.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
-public:
- explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_);
- ~IStorageAccessor() override;
-
-private:
- void GetSize(HLERequestContext& ctx);
- void Write(HLERequestContext& ctx);
- void Read(HLERequestContext& ctx);
-
- const std::shared_ptr<LibraryAppletStorage> impl;
-};
-
-class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> {
-public:
- explicit ITransferStorageAccessor(Core::System& system_,
- std::shared_ptr<LibraryAppletStorage> impl_);
- ~ITransferStorageAccessor() override;
-
-private:
- void GetSize(HLERequestContext& ctx);
- void GetHandle(HLERequestContext& ctx);
-
- const std::shared_ptr<LibraryAppletStorage> impl;
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp
deleted file mode 100644
index 38643408e..000000000
--- a/src/core/hle/service/am/system_applet_proxy.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet_common_functions.h"
-#include "core/hle/service/am/application_creator.h"
-#include "core/hle/service/am/audio_controller.h"
-#include "core/hle/service/am/common_state_getter.h"
-#include "core/hle/service/am/debug_functions.h"
-#include "core/hle/service/am/display_controller.h"
-#include "core/hle/service/am/global_state_controller.h"
-#include "core/hle/service/am/home_menu_functions.h"
-#include "core/hle/service/am/library_applet_creator.h"
-#include "core/hle/service/am/library_applet_self_accessor.h"
-#include "core/hle/service/am/process_winding_controller.h"
-#include "core/hle/service/am/self_controller.h"
-#include "core/hle/service/am/system_applet_proxy.h"
-#include "core/hle/service/am/window_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> applet_, Core::System& system_)
- : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
- applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
- {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
- {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
- {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
- {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
- {10, nullptr, "GetProcessWindingController"},
- {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
- {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
- {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
- {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
- {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
- {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-ISystemAppletProxy::~ISystemAppletProxy() = default;
-
-void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ICommonStateGetter>(system, applet);
-}
-
-void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
-}
-
-void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IWindowController>(system, applet);
-}
-
-void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioController>(system);
-}
-
-void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDisplayController>(system, applet);
-}
-
-void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
-}
-
-void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHomeMenuFunctions>(system);
-}
-
-void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IGlobalStateController>(system);
-}
-
-void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationCreator>(system);
-}
-
-void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
-}
-
-void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IDebugFunctions>(system);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h
deleted file mode 100644
index 0390cd1e5..000000000
--- a/src/core/hle/service/am/system_applet_proxy.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/am/applet_message_queue.h"
-#include "core/hle/service/service.h"
-
-namespace Service::AM {
-
-struct Applet;
-
-class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
-public:
- explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
- std::shared_ptr<Applet> applet_, Core::System& system_);
- ~ISystemAppletProxy();
-
-private:
- void GetCommonStateGetter(HLERequestContext& ctx);
- void GetSelfController(HLERequestContext& ctx);
- void GetWindowController(HLERequestContext& ctx);
- void GetAudioController(HLERequestContext& ctx);
- void GetDisplayController(HLERequestContext& ctx);
- void GetLibraryAppletCreator(HLERequestContext& ctx);
- void GetHomeMenuFunctions(HLERequestContext& ctx);
- void GetGlobalStateController(HLERequestContext& ctx);
- void GetApplicationCreator(HLERequestContext& ctx);
- void GetAppletCommonFunctions(HLERequestContext& ctx);
- void GetDebugFunctions(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nvnflinger;
- std::shared_ptr<Applet> applet;
-};
-
-} // namespace Service::AM
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/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp
deleted file mode 100644
index c07ef228b..000000000
--- a/src/core/hle/service/am/window_controller.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/applet.h"
-#include "core/hle/service/am/window_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::AM {
-
-IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_)
- : ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "CreateWindow"},
- {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
- {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
- {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
- {11, nullptr, "ReleaseForegroundRights"},
- {12, nullptr, "RejectToChangeIntoBackground"},
- {20, &IWindowController::SetAppletWindowVisibility, "SetAppletWindowVisibility"},
- {21, &IWindowController::SetAppletGpuTimeSlice, "SetAppletGpuTimeSlice"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IWindowController::~IWindowController() = default;
-
-void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(applet->aruid);
-}
-
-void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
- u64 aruid = 0;
- if (auto caller = applet->caller_applet.lock(); caller) {
- aruid = caller->aruid;
- }
-
- LOG_WARNING(Service_AM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(aruid);
-}
-
-void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
- LOG_WARNING(Service_AM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IWindowController::SetAppletWindowVisibility(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::RequestParser rp{ctx};
- const bool visible = rp.Pop<bool>();
-
- applet->system_buffer_manager.SetWindowVisibility(visible);
- applet->hid_registration.EnableAppletToGetInput(visible);
-
- if (visible) {
- applet->focus_state = FocusState::InFocus;
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
- } else {
- applet->focus_state = FocusState::NotInFocus;
- applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IWindowController::SetAppletGpuTimeSlice(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto time_slice = rp.Pop<s64>();
-
- LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h
deleted file mode 100644
index a28219abe..000000000
--- a/src/core/hle/service/am/window_controller.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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::AM {
-
-struct Applet;
-
-class IWindowController final : public ServiceFramework<IWindowController> {
-public:
- explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_);
- ~IWindowController() override;
-
-private:
- void GetAppletResourceUserId(HLERequestContext& ctx);
- void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
- void AcquireForegroundRights(HLERequestContext& ctx);
- void SetAppletWindowVisibility(HLERequestContext& ctx);
- void SetAppletGpuTimeSlice(HLERequestContext& ctx);
-
- const std::shared_ptr<Applet> applet;
-};
-
-} // 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 3101cf447..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/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 2dc23e674..d120dade8 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -3,141 +3,18 @@
#include <memory>
-#include "common/logging/log.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
#include "core/hle/service/btm/btm.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/btm/btm_debug.h"
+#include "core/hle/service/btm/btm_system.h"
+#include "core/hle/service/btm/btm_user.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
namespace Service::BTM {
-class IBtmUserCore final : public ServiceFramework<IBtmUserCore> {
+class IBtm final : public ServiceFramework<IBtm> {
public:
- explicit IBtmUserCore(Core::System& system_)
- : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"},
- {1, nullptr, "GetBleScanFilterParameter"},
- {2, nullptr, "GetBleScanFilterParameter2"},
- {3, nullptr, "StartBleScanForGeneral"},
- {4, nullptr, "StopBleScanForGeneral"},
- {5, nullptr, "GetBleScanResultsForGeneral"},
- {6, nullptr, "StartBleScanForPaired"},
- {7, nullptr, "StopBleScanForPaired"},
- {8, nullptr, "StartBleScanForSmartDevice"},
- {9, nullptr, "StopBleScanForSmartDevice"},
- {10, nullptr, "GetBleScanResultsForSmartDevice"},
- {17, &IBtmUserCore::AcquireBleConnectionEvent, "AcquireBleConnectionEvent"},
- {18, nullptr, "BleConnect"},
- {19, nullptr, "BleDisconnect"},
- {20, nullptr, "BleGetConnectionState"},
- {21, nullptr, "AcquireBlePairingEvent"},
- {22, nullptr, "BlePairDevice"},
- {23, nullptr, "BleUnPairDevice"},
- {24, nullptr, "BleUnPairDevice2"},
- {25, nullptr, "BleGetPairedDevices"},
- {26, &IBtmUserCore::AcquireBleServiceDiscoveryEvent, "AcquireBleServiceDiscoveryEvent"},
- {27, nullptr, "GetGattServices"},
- {28, nullptr, "GetGattService"},
- {29, nullptr, "GetGattIncludedServices"},
- {30, nullptr, "GetBelongingGattService"},
- {31, nullptr, "GetGattCharacteristics"},
- {32, nullptr, "GetGattDescriptors"},
- {33, &IBtmUserCore::AcquireBleMtuConfigEvent, "AcquireBleMtuConfigEvent"},
- {34, nullptr, "ConfigureBleMtu"},
- {35, nullptr, "GetBleMtu"},
- {36, nullptr, "RegisterBleGattDataPath"},
- {37, nullptr, "UnregisterBleGattDataPath"},
- };
- // clang-format on
- RegisterHandlers(functions);
-
- scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent");
- connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent");
- service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent");
- config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent");
- }
-
- ~IBtmUserCore() override {
- service_context.CloseEvent(scan_event);
- service_context.CloseEvent(connection_event);
- service_context.CloseEvent(service_discovery_event);
- service_context.CloseEvent(config_event);
- }
-
-private:
- void AcquireBleScanEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3, 1};
- rb.Push(ResultSuccess);
- rb.Push(true);
- rb.PushCopyObjects(scan_event->GetReadableEvent());
- }
-
- void AcquireBleConnectionEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3, 1};
- rb.Push(ResultSuccess);
- rb.Push(true);
- rb.PushCopyObjects(connection_event->GetReadableEvent());
- }
-
- void AcquireBleServiceDiscoveryEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3, 1};
- rb.Push(ResultSuccess);
- rb.Push(true);
- rb.PushCopyObjects(service_discovery_event->GetReadableEvent());
- }
-
- void AcquireBleMtuConfigEvent(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3, 1};
- rb.Push(ResultSuccess);
- rb.Push(true);
- rb.PushCopyObjects(config_event->GetReadableEvent());
- }
-
- KernelHelpers::ServiceContext service_context;
-
- Kernel::KEvent* scan_event;
- Kernel::KEvent* connection_event;
- Kernel::KEvent* service_discovery_event;
- Kernel::KEvent* config_event;
-};
-
-class BTM_USR final : public ServiceFramework<BTM_USR> {
-public:
- explicit BTM_USR(Core::System& system_) : ServiceFramework{system_, "btm:u"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &BTM_USR::GetCore, "GetCore"},
- };
- // clang-format on
- RegisterHandlers(functions);
- }
-
-private:
- void GetCore(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IBtmUserCore>(system);
- }
-};
-
-class BTM final : public ServiceFramework<BTM> {
-public:
- explicit BTM(Core::System& system_) : ServiceFramework{system_, "btm"} {
+ explicit IBtm(Core::System& system_) : ServiceFramework{system_, "btm"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetState"},
@@ -232,144 +109,13 @@ public:
}
};
-class BTM_DBG final : public ServiceFramework<BTM_DBG> {
-public:
- explicit BTM_DBG(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "AcquireDiscoveryEvent"},
- {1, nullptr, "StartDiscovery"},
- {2, nullptr, "CancelDiscovery"},
- {3, nullptr, "GetDeviceProperty"},
- {4, nullptr, "CreateBond"},
- {5, nullptr, "CancelBond"},
- {6, nullptr, "SetTsiMode"},
- {7, nullptr, "GeneralTest"},
- {8, nullptr, "HidConnect"},
- {9, nullptr, "GeneralGet"},
- {10, nullptr, "GetGattClientDisconnectionReason"},
- {11, nullptr, "GetBleConnectionParameter"},
- {12, nullptr, "GetBleConnectionParameterRequest"},
- {13, nullptr, "Unknown13"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
-public:
- explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"},
- {1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"},
- {2, nullptr, "ClearGamepadPairingDatabase"},
- {3, nullptr, "GetPairedGamepadCount"},
- {4, nullptr, "EnableRadio"},
- {5, nullptr, "DisableRadio"},
- {6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"},
- {7, nullptr, "AcquireRadioEvent"},
- {8, nullptr, "AcquireGamepadPairingEvent"},
- {9, nullptr, "IsGamepadPairingStarted"},
- {10, nullptr, "StartAudioDeviceDiscovery"},
- {11, nullptr, "StopAudioDeviceDiscovery"},
- {12, nullptr, "IsDiscoveryingAudioDevice"},
- {13, nullptr, "GetDiscoveredAudioDevice"},
- {14, nullptr, "AcquireAudioDeviceConnectionEvent"},
- {15, nullptr, "ConnectAudioDevice"},
- {16, nullptr, "IsConnectingAudioDevice"},
- {17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"},
- {18, nullptr, "DisconnectAudioDevice"},
- {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"},
- {20, &IBtmSystemCore::GetPairedAudioDevices, "GetPairedAudioDevices"},
- {21, nullptr, "RemoveAudioDevicePairing"},
- {22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"},
- {23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"}
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void IsRadioEnabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(true);
- }
-
- void StartGamepadPairing(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void CancelGamepadPairing(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetConnectedAudioDevices(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(0);
- }
-
- void GetPairedAudioDevices(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(0);
- }
-
- void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-};
-
-class BTM_SYS final : public ServiceFramework<BTM_SYS> {
-public:
- explicit BTM_SYS(Core::System& system_) : ServiceFramework{system_, "btm:sys"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &BTM_SYS::GetCore, "GetCore"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void GetCore(HLERequestContext& ctx) {
- LOG_WARNING(Service_BTM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IBtmSystemCore>(system);
- }
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("btm", std::make_shared<BTM>(system));
- server_manager->RegisterNamedService("btm:dbg", std::make_shared<BTM_DBG>(system));
- server_manager->RegisterNamedService("btm:sys", std::make_shared<BTM_SYS>(system));
- server_manager->RegisterNamedService("btm:u", std::make_shared<BTM_USR>(system));
+ server_manager->RegisterNamedService("btm", std::make_shared<IBtm>(system));
+ server_manager->RegisterNamedService("btm:dbg", std::make_shared<IBtmDebug>(system));
+ server_manager->RegisterNamedService("btm:sys", std::make_shared<IBtmSystem>(system));
+ server_manager->RegisterNamedService("btm:u", std::make_shared<IBtmUser>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h
index a99b34364..0bf77d053 100644
--- a/src/core/hle/service/btm/btm.h
+++ b/src/core/hle/service/btm/btm.h
@@ -3,10 +3,6 @@
#pragma once
-namespace Service::SM {
-class ServiceManager;
-}
-
namespace Core {
class System;
};
diff --git a/src/core/hle/service/btm/btm_debug.cpp b/src/core/hle/service/btm/btm_debug.cpp
new file mode 100644
index 000000000..4d61d2641
--- /dev/null
+++ b/src/core/hle/service/btm/btm_debug.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/btm/btm_debug.h"
+
+namespace Service::BTM {
+
+IBtmDebug::IBtmDebug(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "AcquireDiscoveryEvent"},
+ {1, nullptr, "StartDiscovery"},
+ {2, nullptr, "CancelDiscovery"},
+ {3, nullptr, "GetDeviceProperty"},
+ {4, nullptr, "CreateBond"},
+ {5, nullptr, "CancelBond"},
+ {6, nullptr, "SetTsiMode"},
+ {7, nullptr, "GeneralTest"},
+ {8, nullptr, "HidConnect"},
+ {9, nullptr, "GeneralGet"},
+ {10, nullptr, "GetGattClientDisconnectionReason"},
+ {11, nullptr, "GetBleConnectionParameter"},
+ {12, nullptr, "GetBleConnectionParameterRequest"},
+ {13, nullptr, "Unknown13"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IBtmDebug::~IBtmDebug() = default;
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_debug.h b/src/core/hle/service/btm/btm_debug.h
new file mode 100644
index 000000000..bf4f7e14f
--- /dev/null
+++ b/src/core/hle/service/btm/btm_debug.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BTM {
+
+class IBtmDebug final : public ServiceFramework<IBtmDebug> {
+public:
+ explicit IBtmDebug(Core::System& system_);
+ ~IBtmDebug() override;
+};
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_system.cpp b/src/core/hle/service/btm/btm_system.cpp
new file mode 100644
index 000000000..99718a7b0
--- /dev/null
+++ b/src/core/hle/service/btm/btm_system.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/service/btm/btm_system.h"
+#include "core/hle/service/btm/btm_system_core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/service.h"
+
+namespace Service::BTM {
+
+IBtmSystem::IBtmSystem(Core::System& system_) : ServiceFramework{system_, "btm:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IBtmSystem::GetCore>, "GetCore"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IBtmSystem::~IBtmSystem() = default;
+
+Result IBtmSystem::GetCore(OutInterface<IBtmSystemCore> out_interface) {
+ LOG_WARNING(Service_BTM, "called");
+
+ *out_interface = std::make_shared<IBtmSystemCore>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_system.h b/src/core/hle/service/btm/btm_system.h
new file mode 100644
index 000000000..fe1c6dbd7
--- /dev/null
+++ b/src/core/hle/service/btm/btm_system.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BTM {
+class IBtmSystemCore;
+
+class IBtmSystem final : public ServiceFramework<IBtmSystem> {
+public:
+ explicit IBtmSystem(Core::System& system_);
+ ~IBtmSystem() override;
+
+private:
+ Result GetCore(OutInterface<IBtmSystemCore> out_interface);
+};
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_system_core.cpp b/src/core/hle/service/btm/btm_system_core.cpp
new file mode 100644
index 000000000..4bc8a9e8b
--- /dev/null
+++ b/src/core/hle/service/btm/btm_system_core.cpp
@@ -0,0 +1,127 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/service/btm/btm_system_core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/set/system_settings_server.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BTM {
+
+IBtmSystemCore::IBtmSystemCore(Core::System& system_)
+ : ServiceFramework{system_, "IBtmSystemCore"}, service_context{system_, "IBtmSystemCore"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IBtmSystemCore::StartGamepadPairing>, "StartGamepadPairing"},
+ {1, C<&IBtmSystemCore::CancelGamepadPairing>, "CancelGamepadPairing"},
+ {2, nullptr, "ClearGamepadPairingDatabase"},
+ {3, nullptr, "GetPairedGamepadCount"},
+ {4, C<&IBtmSystemCore::EnableRadio>, "EnableRadio"},
+ {5, C<&IBtmSystemCore::DisableRadio>, "DisableRadio"},
+ {6, C<&IBtmSystemCore::IsRadioEnabled>, "IsRadioEnabled"},
+ {7, C<&IBtmSystemCore::AcquireRadioEvent>, "AcquireRadioEvent"},
+ {8, nullptr, "AcquireGamepadPairingEvent"},
+ {9, nullptr, "IsGamepadPairingStarted"},
+ {10, nullptr, "StartAudioDeviceDiscovery"},
+ {11, nullptr, "StopAudioDeviceDiscovery"},
+ {12, nullptr, "IsDiscoveryingAudioDevice"},
+ {13, nullptr, "GetDiscoveredAudioDevice"},
+ {14, C<&IBtmSystemCore::AcquireAudioDeviceConnectionEvent>, "AcquireAudioDeviceConnectionEvent"},
+ {15, nullptr, "ConnectAudioDevice"},
+ {16, nullptr, "IsConnectingAudioDevice"},
+ {17, C<&IBtmSystemCore::GetConnectedAudioDevices>, "GetConnectedAudioDevices"},
+ {18, nullptr, "DisconnectAudioDevice"},
+ {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"},
+ {20, C<&IBtmSystemCore::GetPairedAudioDevices>, "GetPairedAudioDevices"},
+ {21, nullptr, "RemoveAudioDevicePairing"},
+ {22, C<&IBtmSystemCore::RequestAudioDeviceConnectionRejection>, "RequestAudioDeviceConnectionRejection"},
+ {23, C<&IBtmSystemCore::CancelAudioDeviceConnectionRejection>, "CancelAudioDeviceConnectionRejection"}
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ radio_event = service_context.CreateEvent("IBtmSystemCore::RadioEvent");
+ audio_device_connection_event =
+ service_context.CreateEvent("IBtmSystemCore::AudioDeviceConnectionEvent");
+
+ m_set_sys =
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
+}
+
+IBtmSystemCore::~IBtmSystemCore() {
+ service_context.CloseEvent(radio_event);
+ service_context.CloseEvent(audio_device_connection_event);
+}
+
+Result IBtmSystemCore::StartGamepadPairing() {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::CancelGamepadPairing() {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::EnableRadio() {
+ LOG_DEBUG(Service_BTM, "called");
+
+ R_RETURN(m_set_sys->SetBluetoothEnableFlag(true));
+}
+Result IBtmSystemCore::DisableRadio() {
+ LOG_DEBUG(Service_BTM, "called");
+
+ R_RETURN(m_set_sys->SetBluetoothEnableFlag(false));
+}
+
+Result IBtmSystemCore::IsRadioEnabled(Out<bool> out_is_enabled) {
+ LOG_DEBUG(Service_BTM, "called");
+
+ R_RETURN(m_set_sys->GetBluetoothEnableFlag(out_is_enabled));
+}
+
+Result IBtmSystemCore::AcquireRadioEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_is_valid = true;
+ *out_event = &radio_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::AcquireAudioDeviceConnectionEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_event = &audio_device_connection_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::GetConnectedAudioDevices(
+ Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_count = 0;
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::GetPairedAudioDevices(
+ Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_count = 0;
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid);
+ R_SUCCEED();
+}
+
+Result IBtmSystemCore::CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid);
+ R_SUCCEED();
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_system_core.h b/src/core/hle/service/btm/btm_system_core.h
new file mode 100644
index 000000000..06498b21e
--- /dev/null
+++ b/src/core/hle/service/btm/btm_system_core.h
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KEvent;
+class KReadableEvent;
+} // namespace Kernel
+
+namespace Core {
+class System;
+}
+
+namespace Service::Set {
+class ISystemSettingsServer;
+}
+
+namespace Service::BTM {
+
+class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
+public:
+ explicit IBtmSystemCore(Core::System& system_);
+ ~IBtmSystemCore() override;
+
+private:
+ Result StartGamepadPairing();
+ Result CancelGamepadPairing();
+ Result EnableRadio();
+ Result DisableRadio();
+ Result IsRadioEnabled(Out<bool> out_is_enabled);
+
+ Result AcquireRadioEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result AcquireAudioDeviceConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result GetConnectedAudioDevices(
+ Out<s32> out_count,
+ OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices);
+
+ Result GetPairedAudioDevices(
+ Out<s32> out_count,
+ OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices);
+
+ Result RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid);
+ Result CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid);
+
+ KernelHelpers::ServiceContext service_context;
+
+ Kernel::KEvent* radio_event;
+ Kernel::KEvent* audio_device_connection_event;
+ std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
+};
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_user.cpp b/src/core/hle/service/btm/btm_user.cpp
new file mode 100644
index 000000000..d2e228f8d
--- /dev/null
+++ b/src/core/hle/service/btm/btm_user.cpp
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/service/btm/btm_user.h"
+#include "core/hle/service/btm/btm_user_core.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BTM {
+
+IBtmUser::IBtmUser(Core::System& system_) : ServiceFramework{system_, "btm:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IBtmUser::GetCore>, "GetCore"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IBtmUser::~IBtmUser() = default;
+
+Result IBtmUser::GetCore(OutInterface<IBtmUserCore> out_interface) {
+ LOG_WARNING(Service_BTM, "called");
+
+ *out_interface = std::make_shared<IBtmUserCore>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_user.h b/src/core/hle/service/btm/btm_user.h
new file mode 100644
index 000000000..d9ee5db45
--- /dev/null
+++ b/src/core/hle/service/btm/btm_user.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::BTM {
+class IBtmUserCore;
+
+class IBtmUser final : public ServiceFramework<IBtmUser> {
+public:
+ explicit IBtmUser(Core::System& system_);
+ ~IBtmUser() override;
+
+private:
+ Result GetCore(OutInterface<IBtmUserCore> out_interface);
+};
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_user_core.cpp b/src/core/hle/service/btm/btm_user_core.cpp
new file mode 100644
index 000000000..6f9fa589b
--- /dev/null
+++ b/src/core/hle/service/btm/btm_user_core.cpp
@@ -0,0 +1,103 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/core.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/btm/btm_user_core.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::BTM {
+
+IBtmUserCore::IBtmUserCore(Core::System& system_)
+ : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IBtmUserCore::AcquireBleScanEvent>, "AcquireBleScanEvent"},
+ {1, nullptr, "GetBleScanFilterParameter"},
+ {2, nullptr, "GetBleScanFilterParameter2"},
+ {3, nullptr, "StartBleScanForGeneral"},
+ {4, nullptr, "StopBleScanForGeneral"},
+ {5, nullptr, "GetBleScanResultsForGeneral"},
+ {6, nullptr, "StartBleScanForPaired"},
+ {7, nullptr, "StopBleScanForPaired"},
+ {8, nullptr, "StartBleScanForSmartDevice"},
+ {9, nullptr, "StopBleScanForSmartDevice"},
+ {10, nullptr, "GetBleScanResultsForSmartDevice"},
+ {17, C<&IBtmUserCore::AcquireBleConnectionEvent>, "AcquireBleConnectionEvent"},
+ {18, nullptr, "BleConnect"},
+ {19, nullptr, "BleDisconnect"},
+ {20, nullptr, "BleGetConnectionState"},
+ {21, nullptr, "AcquireBlePairingEvent"},
+ {22, nullptr, "BlePairDevice"},
+ {23, nullptr, "BleUnPairDevice"},
+ {24, nullptr, "BleUnPairDevice2"},
+ {25, nullptr, "BleGetPairedDevices"},
+ {26, C<&IBtmUserCore::AcquireBleServiceDiscoveryEvent>, "AcquireBleServiceDiscoveryEvent"},
+ {27, nullptr, "GetGattServices"},
+ {28, nullptr, "GetGattService"},
+ {29, nullptr, "GetGattIncludedServices"},
+ {30, nullptr, "GetBelongingGattService"},
+ {31, nullptr, "GetGattCharacteristics"},
+ {32, nullptr, "GetGattDescriptors"},
+ {33, C<&IBtmUserCore::AcquireBleMtuConfigEvent>, "AcquireBleMtuConfigEvent"},
+ {34, nullptr, "ConfigureBleMtu"},
+ {35, nullptr, "GetBleMtu"},
+ {36, nullptr, "RegisterBleGattDataPath"},
+ {37, nullptr, "UnregisterBleGattDataPath"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+
+ scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent");
+ connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent");
+ service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent");
+ config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent");
+}
+
+IBtmUserCore::~IBtmUserCore() {
+ service_context.CloseEvent(scan_event);
+ service_context.CloseEvent(connection_event);
+ service_context.CloseEvent(service_discovery_event);
+ service_context.CloseEvent(config_event);
+}
+
+Result IBtmUserCore::AcquireBleScanEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_is_valid = true;
+ *out_event = &scan_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IBtmUserCore::AcquireBleConnectionEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_is_valid = true;
+ *out_event = &connection_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IBtmUserCore::AcquireBleServiceDiscoveryEvent(
+ Out<bool> out_is_valid, OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_is_valid = true;
+ *out_event = &service_discovery_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IBtmUserCore::AcquireBleMtuConfigEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_BTM, "(STUBBED) called");
+
+ *out_is_valid = true;
+ *out_event = &config_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm_user_core.h b/src/core/hle/service/btm/btm_user_core.h
new file mode 100644
index 000000000..dc0a22e81
--- /dev/null
+++ b/src/core/hle/service/btm/btm_user_core.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KEvent;
+class KReadableEvent;
+} // namespace Kernel
+
+namespace Core {
+class System;
+}
+
+namespace Service::BTM {
+
+class IBtmUserCore final : public ServiceFramework<IBtmUserCore> {
+public:
+ explicit IBtmUserCore(Core::System& system_);
+ ~IBtmUserCore() override;
+
+private:
+ Result AcquireBleScanEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result AcquireBleConnectionEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result AcquireBleServiceDiscoveryEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result AcquireBleMtuConfigEvent(Out<bool> out_is_valid,
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ KernelHelpers::ServiceContext service_context;
+
+ Kernel::KEvent* scan_event;
+ Kernel::KEvent* connection_event;
+ Kernel::KEvent* service_discovery_event;
+ Kernel::KEvent* config_event;
+};
+
+} // namespace Service::BTM
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 0c27e8029..059ac3fc9 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -21,19 +21,6 @@
namespace Service::Glue::Time {
namespace {
-
-template <typename T>
-T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
- const char* category, const char* name) {
- std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
- ASSERT(res == ResultSuccess);
-
- T v{};
- std::memcpy(&v, interval_buf.data(), sizeof(T));
- return v;
-}
-
s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
constexpr auto is_leap = [](s32 year) -> bool {
return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
@@ -65,13 +52,15 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
Service::PSC::Time::CalendarTime calendar{
- .year = GetSettingsItemValue<s16>(set_sys, "time", "standard_user_clock_initial_year"),
+ .year = 2000,
.month = 1,
.day = 1,
.hour = 0,
.minute = 0,
.second = 0,
};
+ set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time",
+ "standard_user_clock_initial_year");
return CalendarTimeToEpoch(calendar);
}
@@ -124,7 +113,7 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
Service::PSC::Time::SystemClockContext user_clock_context{};
- res = m_set_sys->GetUserSystemClockContext(user_clock_context);
+ res = m_set_sys->GetUserSystemClockContext(&user_clock_context);
ASSERT(res == ResultSuccess);
// TODO the local clock should initialise with this epoch time, and be updated somewhere else on
@@ -140,11 +129,12 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
Service::PSC::Time::SystemClockContext network_clock_context{};
- res = m_set_sys->GetNetworkSystemClockContext(network_clock_context);
+ res = m_set_sys->GetNetworkSystemClockContext(&network_clock_context);
ASSERT(res == ResultSuccess);
- auto network_accuracy_m{GetSettingsItemValue<s32>(
- m_set_sys, "time", "standard_network_clock_sufficient_accuracy_minutes")};
+ s32 network_accuracy_m{};
+ m_set_sys->GetSettingsItemValueImpl<s32>(network_accuracy_m, "time",
+ "standard_network_clock_sufficient_accuracy_minutes");
auto one_minute_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
s64 network_accuracy_ns{network_accuracy_m * one_minute_ns};
@@ -153,12 +143,12 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
bool is_automatic_correction_enabled{};
- res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(is_automatic_correction_enabled);
+ res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(&is_automatic_correction_enabled);
ASSERT(res == ResultSuccess);
Service::PSC::Time::SteadyClockTimePoint automatic_correction_time_point{};
res = m_set_sys->GetUserSystemClockAutomaticCorrectionUpdatedTime(
- automatic_correction_time_point);
+ &automatic_correction_time_point);
ASSERT(res == ResultSuccess);
res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled,
@@ -196,13 +186,17 @@ 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);
+ auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
ASSERT(res == ResultSuccess);
s64 external_steady_clock_internal_offset_s{};
- res = m_set_sys->GetExternalSteadyClockInternalOffset(external_steady_clock_internal_offset_s);
+ res = m_set_sys->GetExternalSteadyClockInternalOffset(&external_steady_clock_internal_offset_s);
ASSERT(res == ResultSuccess);
auto one_second_ns{
@@ -210,8 +204,9 @@ Result TimeManager::SetupStandardSteadyClockCore() {
s64 external_steady_clock_internal_offset_ns{external_steady_clock_internal_offset_s *
one_second_ns};
- s32 standard_steady_clock_test_offset_m{
- GetSettingsItemValue<s32>(m_set_sys, "time", "standard_steady_clock_test_offset_minutes")};
+ s32 standard_steady_clock_test_offset_m{};
+ m_set_sys->GetSettingsItemValueImpl<s32>(standard_steady_clock_test_offset_m, "time",
+ "standard_steady_clock_test_offset_minutes");
auto one_minute_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
s64 standard_steady_clock_test_offset_ns{standard_steady_clock_test_offset_m * one_minute_ns};
@@ -237,7 +232,7 @@ Result TimeManager::SetupStandardSteadyClockCore() {
Result TimeManager::SetupTimeZoneServiceCore() {
Service::PSC::Time::LocationName name{};
- auto res = m_set_sys->GetDeviceTimeZoneLocationName(name);
+ auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name);
ASSERT(res == ResultSuccess);
auto configured_zone = GetTimeZoneString(name);
@@ -255,7 +250,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
}
Service::PSC::Time::SteadyClockTimePoint time_point{};
- res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(time_point);
+ res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point);
ASSERT(res == ResultSuccess);
auto location_count = GetTimeZoneCount();
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 f8c1218f3..b801faef2 100644
--- a/src/core/hle/service/glue/time/static.cpp
+++ b/src/core/hle/service/glue/time/static.cpp
@@ -20,19 +20,6 @@
#include "core/hle/service/sm/sm.h"
namespace Service::Glue::Time {
-namespace {
-template <typename T>
-T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
- const char* category, const char* name) {
- std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
- ASSERT(res == ResultSuccess);
-
- T v{};
- std::memcpy(&v, interval_buf.data(), sizeof(T));
- return v;
-}
-} // namespace
StaticService::StaticService(Core::System& system_,
Service::PSC::Time::StaticServiceSetupInfo setup_info,
@@ -155,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));
@@ -179,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);
+ };
- *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
- R_SUCCEED();
+ 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));
@@ -201,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));
}
@@ -218,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));
@@ -231,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/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp
index 8787f2dcd..b28569b68 100644
--- a/src/core/hle/service/glue/time/worker.cpp
+++ b/src/core/hle/service/glue/time/worker.cpp
@@ -27,7 +27,7 @@ template <typename T>
T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
const char* category, const char* name) {
std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
+ auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name);
ASSERT(res == ResultSuccess);
T v{};
diff --git a/src/core/hle/service/ldn/lan_discovery.cpp b/src/core/hle/service/ldn/lan_discovery.cpp
index 8f3c04550..b9db19618 100644
--- a/src/core/hle/service/ldn/lan_discovery.cpp
+++ b/src/core/hle/service/ldn/lan_discovery.cpp
@@ -85,15 +85,14 @@ Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network) const {
}
Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network,
- std::vector<NodeLatestUpdate>& out_updates,
- std::size_t buffer_count) {
- if (buffer_count > NodeCountMax) {
+ std::span<NodeLatestUpdate> out_updates) {
+ if (out_updates.size() > NodeCountMax) {
return ResultInvalidBufferCount;
}
if (state == State::AccessPointCreated || state == State::StationConnected) {
std::memcpy(&out_network, &network_info, sizeof(network_info));
- for (std::size_t i = 0; i < buffer_count; i++) {
+ for (std::size_t i = 0; i < out_updates.size(); i++) {
out_updates[i].state_change = node_changes[i].state_change;
node_changes[i].state_change = NodeStateChange::None;
}
@@ -107,15 +106,8 @@ DisconnectReason LANDiscovery::GetDisconnectReason() const {
return disconnect_reason;
}
-Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
+Result LANDiscovery::Scan(std::span<NetworkInfo> out_networks, s16& out_count,
const ScanFilter& filter) {
- if (!IsFlagSet(filter.flag, ScanFilterFlag::NetworkType) ||
- filter.network_type <= NetworkType::All) {
- if (!IsFlagSet(filter.flag, ScanFilterFlag::Ssid) && filter.ssid.length >= SsidLengthMax) {
- return ResultBadInput;
- }
- }
-
{
std::scoped_lock lock{packet_mutex};
scan_results.clear();
@@ -128,7 +120,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
std::scoped_lock lock{packet_mutex};
for (const auto& [key, info] : scan_results) {
- if (count >= networks.size()) {
+ if (out_count >= static_cast<s16>(out_networks.size())) {
break;
}
@@ -159,7 +151,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
}
}
- networks[count++] = info;
+ out_networks[out_count++] = info;
}
return ResultSuccess;
diff --git a/src/core/hle/service/ldn/lan_discovery.h b/src/core/hle/service/ldn/lan_discovery.h
index 3833cd764..8f7a8dfc4 100644
--- a/src/core/hle/service/ldn/lan_discovery.h
+++ b/src/core/hle/service/ldn/lan_discovery.h
@@ -54,11 +54,10 @@ public:
void SetState(State new_state);
Result GetNetworkInfo(NetworkInfo& out_network) const;
- Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates,
- std::size_t buffer_count);
+ Result GetNetworkInfo(NetworkInfo& out_network, std::span<NodeLatestUpdate> out_updates);
DisconnectReason GetDisconnectReason() const;
- Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter);
+ Result Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter);
Result SetAdvertiseData(std::span<const u8> data);
Result OpenAccessPoint();
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 961f89a14..f2d638c30 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -1,36 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <memory>
-
#include "core/core.h"
-#include "core/hle/service/ldn/lan_discovery.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/ldn.h"
-#include "core/hle/service/ldn/ldn_results.h"
-#include "core/hle/service/ldn/ldn_types.h"
-#include "core/hle/service/server_manager.h"
-#include "core/internal_network/network.h"
-#include "core/internal_network/network_interface.h"
-#include "network/network.h"
-
-// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
-#undef CreateEvent
+#include "core/hle/service/ldn/monitor_service.h"
+#include "core/hle/service/ldn/sf_monitor_service.h"
+#include "core/hle/service/ldn/sf_service.h"
+#include "core/hle/service/ldn/sf_service_monitor.h"
+#include "core/hle/service/ldn/system_local_communication_service.h"
+#include "core/hle/service/ldn/user_local_communication_service.h"
namespace Service::LDN {
-class IMonitorService final : public ServiceFramework<IMonitorService> {
+class IMonitorServiceCreator final : public ServiceFramework<IMonitorServiceCreator> {
public:
- explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} {
+ explicit IMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"},
- {1, nullptr, "GetNetworkInfoForMonitor"},
- {2, nullptr, "GetIpv4AddressForMonitor"},
- {3, nullptr, "GetDisconnectReasonForMonitor"},
- {4, nullptr, "GetSecurityParameterForMonitor"},
- {5, nullptr, "GetNetworkConfigForMonitor"},
- {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"},
- {101, nullptr, "FinalizeMonitor"},
+ {0, C<&IMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"}
};
// clang-format on
@@ -38,84 +26,20 @@ public:
}
private:
- void GetStateForMonitor(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(state);
- }
-
- void InitializeMonitor(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- state = State::Initialized;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- State state{State::None};
-};
-
-class LDNM final : public ServiceFramework<LDNM> {
-public:
- explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void CreateMonitorService(HLERequestContext& ctx) {
+ Result CreateMonitorService(OutInterface<IMonitorService> out_interface) {
LOG_DEBUG(Service_LDN, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IMonitorService>(system);
+ *out_interface = std::make_shared<IMonitorService>(system);
+ R_SUCCEED();
}
};
-class ISystemLocalCommunicationService final
- : public ServiceFramework<ISystemLocalCommunicationService> {
+class ISystemServiceCreator final : public ServiceFramework<ISystemServiceCreator> {
public:
- explicit ISystemLocalCommunicationService(Core::System& system_)
- : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
+ explicit ISystemServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "GetState"},
- {1, nullptr, "GetNetworkInfo"},
- {2, nullptr, "GetIpv4Address"},
- {3, nullptr, "GetDisconnectReason"},
- {4, nullptr, "GetSecurityParameter"},
- {5, nullptr, "GetNetworkConfig"},
- {100, nullptr, "AttachStateChangeEvent"},
- {101, nullptr, "GetNetworkInfoLatestUpdate"},
- {102, nullptr, "Scan"},
- {103, nullptr, "ScanPrivate"},
- {104, nullptr, "SetWirelessControllerRestriction"},
- {200, nullptr, "OpenAccessPoint"},
- {201, nullptr, "CloseAccessPoint"},
- {202, nullptr, "CreateNetwork"},
- {203, nullptr, "CreateNetworkPrivate"},
- {204, nullptr, "DestroyNetwork"},
- {205, nullptr, "Reject"},
- {206, nullptr, "SetAdvertiseData"},
- {207, nullptr, "SetStationAcceptPolicy"},
- {208, nullptr, "AddAcceptFilterEntry"},
- {209, nullptr, "ClearAcceptFilter"},
- {300, nullptr, "OpenStation"},
- {301, nullptr, "CloseStation"},
- {302, nullptr, "Connect"},
- {303, nullptr, "ConnectPrivate"},
- {304, nullptr, "Disconnect"},
- {400, nullptr, "InitializeSystem"},
- {401, nullptr, "FinalizeSystem"},
- {402, nullptr, "SetOperationMode"},
- {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"},
+ {0, C<&ISystemServiceCreator::CreateSystemLocalCommunicationService>, "CreateSystemLocalCommunicationService"},
};
// clang-format on
@@ -123,687 +47,78 @@ public:
}
private:
- void InitializeSystem2(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-};
-
-class IUserLocalCommunicationService final
- : public ServiceFramework<IUserLocalCommunicationService> {
-public:
- explicit IUserLocalCommunicationService(Core::System& system_)
- : ServiceFramework{system_, "IUserLocalCommunicationService"},
- service_context{system, "IUserLocalCommunicationService"},
- room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IUserLocalCommunicationService::GetState, "GetState"},
- {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
- {2, &IUserLocalCommunicationService::GetIpv4Address, "GetIpv4Address"},
- {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
- {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
- {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
- {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
- {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
- {102, &IUserLocalCommunicationService::Scan, "Scan"},
- {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
- {104, &IUserLocalCommunicationService::SetWirelessControllerRestriction, "SetWirelessControllerRestriction"},
- {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
- {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
- {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
- {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
- {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
- {205, nullptr, "Reject"},
- {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
- {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
- {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
- {209, nullptr, "ClearAcceptFilter"},
- {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
- {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
- {302, &IUserLocalCommunicationService::Connect, "Connect"},
- {303, nullptr, "ConnectPrivate"},
- {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
- {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
- {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
- {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- state_change_event =
- service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
- }
-
- ~IUserLocalCommunicationService() {
- if (is_initialized) {
- if (auto room_member = room_network.GetRoomMember().lock()) {
- room_member->Unbind(ldn_packet_received);
- }
- }
-
- service_context.CloseEvent(state_change_event);
- }
-
- /// Callback to parse and handle a received LDN packet.
- void OnLDNPacketReceived(const Network::LDNPacket& packet) {
- lan_discovery.ReceivePacket(packet);
- }
-
- void OnEventFired() {
- state_change_event->Signal();
- }
-
- void GetState(HLERequestContext& ctx) {
- State state = State::Error;
-
- if (is_initialized) {
- state = lan_discovery.GetState();
- }
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(state);
- }
-
- void GetNetworkInfo(HLERequestContext& ctx) {
- const auto write_buffer_size = ctx.GetWriteBufferSize();
-
- if (write_buffer_size != sizeof(NetworkInfo)) {
- LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultBadInput);
- return;
- }
-
- NetworkInfo network_info{};
- const auto rc = lan_discovery.GetNetworkInfo(network_info);
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- return;
- }
-
- ctx.WriteBuffer<NetworkInfo>(network_info);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetIpv4Address(HLERequestContext& ctx) {
- const auto network_interface = Network::GetSelectedNetworkInterface();
-
- if (!network_interface) {
- LOG_ERROR(Service_LDN, "No network interface available");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNoIpAddress);
- return;
- }
-
- Ipv4Address current_address{Network::TranslateIPv4(network_interface->ip_address)};
- Ipv4Address subnet_mask{Network::TranslateIPv4(network_interface->subnet_mask)};
-
- // When we're connected to a room, spoof the hosts IP address
- if (auto room_member = room_network.GetRoomMember().lock()) {
- if (room_member->IsConnected()) {
- current_address = room_member->GetFakeIpAddress();
- }
- }
-
- std::reverse(std::begin(current_address), std::end(current_address)); // ntohl
- std::reverse(std::begin(subnet_mask), std::end(subnet_mask)); // ntohl
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushRaw(current_address);
- rb.PushRaw(subnet_mask);
- }
-
- void GetDisconnectReason(HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(lan_discovery.GetDisconnectReason());
- }
-
- void GetSecurityParameter(HLERequestContext& ctx) {
- SecurityParameter security_parameter{};
- NetworkInfo info{};
- const Result rc = lan_discovery.GetNetworkInfo(info);
-
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- return;
- }
-
- security_parameter.session_id = info.network_id.session_id;
- std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
- sizeof(SecurityParameter::data));
-
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(rc);
- rb.PushRaw<SecurityParameter>(security_parameter);
- }
-
- void GetNetworkConfig(HLERequestContext& ctx) {
- NetworkConfig config{};
- NetworkInfo info{};
- const Result rc = lan_discovery.GetNetworkInfo(info);
-
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- return;
- }
-
- config.intent_id = info.network_id.intent_id;
- config.channel = info.common.channel;
- config.node_count_max = info.ldn.node_count_max;
- config.local_communication_version = info.ldn.nodes[0].local_communication_version;
-
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(rc);
- rb.PushRaw<NetworkConfig>(config);
- }
-
- void AttachStateChangeEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(state_change_event->GetReadableEvent());
- }
-
- void GetNetworkInfoLatestUpdate(HLERequestContext& ctx) {
- const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
- const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1);
-
- if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
- LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", network_buffer_size,
- node_buffer_count);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultBadInput);
- return;
- }
-
- NetworkInfo info{};
- std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
-
- const auto rc = lan_discovery.GetNetworkInfo(info, latest_update, latest_update.size());
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- return;
- }
-
- ctx.WriteBuffer(info, 0);
- ctx.WriteBuffer(latest_update, 1);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void Scan(HLERequestContext& ctx) {
- ScanImpl(ctx);
- }
-
- void ScanPrivate(HLERequestContext& ctx) {
- ScanImpl(ctx, true);
- }
-
- void ScanImpl(HLERequestContext& ctx, bool is_private = false) {
- IPC::RequestParser rp{ctx};
- const auto channel{rp.PopEnum<WifiChannel>()};
- const auto scan_filter{rp.PopRaw<ScanFilter>()};
-
- const std::size_t network_info_size = ctx.GetWriteBufferNumElements<NetworkInfo>();
-
- if (network_info_size == 0) {
- LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultBadInput);
- return;
- }
-
- u16 count = 0;
- std::vector<NetworkInfo> network_infos(network_info_size);
- Result rc = lan_discovery.Scan(network_infos, count, scan_filter);
-
- LOG_INFO(Service_LDN,
- "called, channel={}, filter_scan_flag={}, filter_network_type={}, is_private={}",
- channel, scan_filter.flag, scan_filter.network_type, is_private);
-
- ctx.WriteBuffer(network_infos);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(rc);
- rb.Push<u32>(count);
- }
-
- void SetWirelessControllerRestriction(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void OpenAccessPoint(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.OpenAccessPoint());
- }
-
- void CloseAccessPoint(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.CloseAccessPoint());
- }
-
- void CreateNetwork(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- CreateNetworkImpl(ctx);
- }
-
- void CreateNetworkPrivate(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- CreateNetworkImpl(ctx, true);
- }
-
- void CreateNetworkImpl(HLERequestContext& ctx, bool is_private = false) {
- IPC::RequestParser rp{ctx};
-
- const auto security_config{rp.PopRaw<SecurityConfig>()};
- [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>()
- : SecurityParameter{}};
- const auto user_config{rp.PopRaw<UserConfig>()};
- rp.Pop<u32>(); // Padding
- const auto network_Config{rp.PopRaw<NetworkConfig>()};
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.CreateNetwork(security_config, user_config, network_Config));
- }
-
- void DestroyNetwork(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.DestroyNetwork());
- }
-
- void SetAdvertiseData(HLERequestContext& ctx) {
- const auto read_buffer = ctx.ReadBuffer();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
- }
-
- void SetStationAcceptPolicy(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void AddAcceptFilterEntry(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void OpenStation(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.OpenStation());
- }
-
- void CloseStation(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.CloseStation());
- }
-
- void Connect(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- SecurityConfig security_config;
- UserConfig user_config;
- u32 local_communication_version;
- u32 option;
- };
- static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_INFO(Service_LDN,
- "called, passphrase_size={}, security_mode={}, "
- "local_communication_version={}",
- parameters.security_config.passphrase_size,
- parameters.security_config.security_mode, parameters.local_communication_version);
-
- const auto read_buffer = ctx.ReadBuffer();
- if (read_buffer.size() != sizeof(NetworkInfo)) {
- LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultBadInput);
- return;
- }
-
- NetworkInfo network_info{};
- std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.Connect(network_info, parameters.user_config,
- static_cast<u16>(parameters.local_communication_version)));
- }
-
- void Disconnect(HLERequestContext& ctx) {
- LOG_INFO(Service_LDN, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.Disconnect());
- }
-
- void Initialize(HLERequestContext& ctx) {
- const auto rc = InitializeImpl(ctx);
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- void Finalize(HLERequestContext& ctx) {
- if (auto room_member = room_network.GetRoomMember().lock()) {
- room_member->Unbind(ldn_packet_received);
- }
-
- is_initialized = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(lan_discovery.Finalize());
- }
-
- void Initialize2(HLERequestContext& ctx) {
- const auto rc = InitializeImpl(ctx);
- if (rc.IsError()) {
- LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- Result InitializeImpl(HLERequestContext& ctx) {
- const auto network_interface = Network::GetSelectedNetworkInterface();
- if (!network_interface) {
- LOG_ERROR(Service_LDN, "No network interface is set");
- return ResultAirplaneModeEnabled;
- }
-
- if (auto room_member = room_network.GetRoomMember().lock()) {
- ldn_packet_received = room_member->BindOnLdnPacketReceived(
- [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
- } else {
- LOG_ERROR(Service_LDN, "Couldn't bind callback!");
- return ResultAirplaneModeEnabled;
- }
-
- lan_discovery.Initialize([&]() { OnEventFired(); });
- is_initialized = true;
- return ResultSuccess;
- }
-
- KernelHelpers::ServiceContext service_context;
- Kernel::KEvent* state_change_event;
- Network::RoomNetwork& room_network;
- LANDiscovery lan_discovery;
-
- // Callback identifier for the OnLDNPacketReceived event.
- Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
-
- bool is_initialized{};
-};
-
-class LDNS final : public ServiceFramework<LDNS> {
-public:
- explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void CreateSystemLocalCommunicationService(HLERequestContext& ctx) {
+ Result CreateSystemLocalCommunicationService(
+ OutInterface<ISystemLocalCommunicationService> out_interface) {
LOG_DEBUG(Service_LDN, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemLocalCommunicationService>(system);
+ *out_interface = std::make_shared<ISystemLocalCommunicationService>(system);
+ R_SUCCEED();
}
};
-class LDNU final : public ServiceFramework<LDNU> {
+class IUserServiceCreator final : public ServiceFramework<IUserServiceCreator> {
public:
- explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
+ explicit IUserServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
+ {0, C<&IUserServiceCreator::CreateUserLocalCommunicationService>, "CreateUserLocalCommunicationService"},
};
// clang-format on
RegisterHandlers(functions);
}
- void CreateUserLocalCommunicationService(HLERequestContext& ctx) {
+private:
+ Result CreateUserLocalCommunicationService(
+ OutInterface<IUserLocalCommunicationService> out_interface) {
LOG_DEBUG(Service_LDN, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IUserLocalCommunicationService>(system);
+ *out_interface = std::make_shared<IUserLocalCommunicationService>(system);
+ R_SUCCEED();
}
};
-class INetworkService final : public ServiceFramework<INetworkService> {
+class ISfServiceCreator final : public ServiceFramework<ISfServiceCreator> {
public:
- explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} {
+ explicit ISfServiceCreator(Core::System& system_, bool is_system_, const char* name_)
+ : ServiceFramework{system_, name_}, is_system{is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "Initialize"},
- {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
- {264, nullptr, "GetNetworkInterfaceLastError"},
- {272, nullptr, "GetRole"},
- {280, nullptr, "GetAdvertiseData"},
- {288, nullptr, "GetGroupInfo"},
- {296, nullptr, "GetGroupInfo2"},
- {304, nullptr, "GetGroupOwner"},
- {312, nullptr, "GetIpConfig"},
- {320, nullptr, "GetLinkLevel"},
- {512, nullptr, "Scan"},
- {768, nullptr, "CreateGroup"},
- {776, nullptr, "DestroyGroup"},
- {784, nullptr, "SetAdvertiseData"},
- {1536, nullptr, "SendToOtherGroup"},
- {1544, nullptr, "RecvFromOtherGroup"},
- {1552, nullptr, "AddAcceptableGroupId"},
- {1560, nullptr, "ClearAcceptableGroupId"},
+ {0, C<&ISfServiceCreator::CreateNetworkService>, "CreateNetworkService"},
+ {8, C<&ISfServiceCreator::CreateNetworkServiceMonitor>, "CreateNetworkServiceMonitor"},
};
// clang-format on
RegisterHandlers(functions);
}
-};
-
-class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> {
-public:
- explicit INetworkServiceMonitor(Core::System& system_)
- : ServiceFramework{system_, "INetworkServiceMonitor"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &INetworkServiceMonitor::Initialize, "Initialize"},
- {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
- {264, nullptr, "GetNetworkInterfaceLastError"},
- {272, nullptr, "GetRole"},
- {280, nullptr, "GetAdvertiseData"},
- {281, nullptr, "GetAdvertiseData2"},
- {288, nullptr, "GetGroupInfo"},
- {296, nullptr, "GetGroupInfo2"},
- {304, nullptr, "GetGroupOwner"},
- {312, nullptr, "GetIpConfig"},
- {320, nullptr, "GetLinkLevel"},
- {328, nullptr, "AttachJoinEvent"},
- {336, nullptr, "GetMembers"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void Initialize(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultDisabled);
- }
-};
-
-class LP2PAPP final : public ServiceFramework<LP2PAPP> {
-public:
- explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"},
- {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void CreateNetworkervice(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 reserved_input = rp.Pop<u64>();
- const u32 input = rp.Pop<u32>();
-
- LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
- input);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<INetworkService>(system);
- }
-
- void CreateMonitorService(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 reserved_input = rp.Pop<u64>();
-
- LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<INetworkServiceMonitor>(system);
- }
-};
-
-class LP2PSYS final : public ServiceFramework<LP2PSYS> {
-public:
- explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"},
- {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
- void CreateNetworkervice(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 reserved_input = rp.Pop<u64>();
- const u32 input = rp.Pop<u32>();
+private:
+ Result CreateNetworkService(OutInterface<ISfService> out_interface, u32 input,
+ u64 reserved_input) {
LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
input);
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<INetworkService>(system);
+ *out_interface = std::make_shared<ISfService>(system);
+ R_SUCCEED();
}
- void CreateMonitorService(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 reserved_input = rp.Pop<u64>();
-
+ Result CreateNetworkServiceMonitor(OutInterface<ISfServiceMonitor> out_interface,
+ u64 reserved_input) {
LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<INetworkServiceMonitor>(system);
+ *out_interface = std::make_shared<ISfServiceMonitor>(system);
+ R_SUCCEED();
}
-};
-class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
-public:
- explicit ISfMonitorService(Core::System& system_)
- : ServiceFramework{system_, "ISfMonitorService"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &ISfMonitorService::Initialize, "Initialize"},
- {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"},
- {320, nullptr, "GetLinkLevel"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void Initialize(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
- }
-
- void GetGroupInfo(HLERequestContext& ctx) {
- LOG_WARNING(Service_LDN, "(STUBBED) called");
-
- struct GroupInfo {
- std::array<u8, 0x200> info;
- };
-
- GroupInfo group_info{};
-
- ctx.WriteBuffer(group_info);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
+ bool is_system{};
};
-class LP2PM final : public ServiceFramework<LP2PM> {
+class ISfMonitorServiceCreator final : public ServiceFramework<ISfMonitorServiceCreator> {
public:
- explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
+ explicit ISfMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &LP2PM::CreateMonitorService, "CreateMonitorService"},
+ {0, C<&ISfMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"},
};
// clang-format on
@@ -811,28 +126,27 @@ public:
}
private:
- void CreateMonitorService(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 reserved_input = rp.Pop<u64>();
-
+ Result CreateMonitorService(OutInterface<ISfMonitorService> out_interface, u64 reserved_input) {
LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input);
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISfMonitorService>(system);
+ *out_interface = std::make_shared<ISfMonitorService>(system);
+ R_SUCCEED();
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system));
- server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system));
- server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system));
+ server_manager->RegisterNamedService("ldn:m", std::make_shared<IMonitorServiceCreator>(system));
+ server_manager->RegisterNamedService("ldn:s", std::make_shared<ISystemServiceCreator>(system));
+ server_manager->RegisterNamedService("ldn:u", std::make_shared<IUserServiceCreator>(system));
- server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system));
- server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system));
- server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system));
+ server_manager->RegisterNamedService(
+ "lp2p:app", std::make_shared<ISfServiceCreator>(system, false, "lp2p:app"));
+ server_manager->RegisterNamedService(
+ "lp2p:sys", std::make_shared<ISfServiceCreator>(system, true, "lp2p:sys"));
+ server_manager->RegisterNamedService("lp2p:m",
+ std::make_shared<ISfMonitorServiceCreator>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index f4a319168..dae037fa8 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -3,12 +3,6 @@
#pragma once
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/result.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/sm/sm.h"
-
namespace Core {
class System;
}
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
index 44c2c773b..6198aa07b 100644
--- a/src/core/hle/service/ldn/ldn_types.h
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -123,6 +123,18 @@ enum class NodeStatus : u8 {
Connected,
};
+enum class WirelessControllerRestriction : u32 {
+ None,
+ Default,
+};
+
+struct ConnectOption {
+ union {
+ u32 raw;
+ };
+};
+static_assert(sizeof(ConnectOption) == 0x4, "ConnectOption is an invalid size");
+
struct NodeLatestUpdate {
NodeStateChange state_change;
INSERT_PADDING_BYTES(0x7); // Unknown
@@ -139,9 +151,9 @@ static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
struct IntentId {
u64 local_communication_id;
- INSERT_PADDING_BYTES(0x2); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
u16 scene_id;
- INSERT_PADDING_BYTES(0x4); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x4); // Reserved
};
static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
@@ -152,13 +164,14 @@ struct NetworkId {
static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
struct Ssid {
- u8 length{};
- std::array<char, SsidLengthMax + 1> raw{};
+ u8 length;
+ std::array<char, SsidLengthMax + 1> raw;
Ssid() = default;
constexpr explicit Ssid(std::string_view data) {
length = static_cast<u8>(std::min(data.size(), SsidLengthMax));
+ raw = {};
data.copy(raw.data(), length);
raw[length] = 0;
}
@@ -181,7 +194,7 @@ using Ipv4Address = std::array<u8, 4>;
static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
struct MacAddress {
- std::array<u8, 6> raw{};
+ std::array<u8, 6> raw;
friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
};
@@ -211,7 +224,7 @@ struct CommonNetworkInfo {
WifiChannel channel;
LinkLevel link_level;
PackedNetworkType network_type;
- INSERT_PADDING_BYTES(0x4);
+ INSERT_PADDING_BYTES_NOINIT(0x4);
};
static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
@@ -221,9 +234,9 @@ struct NodeInfo {
s8 node_id;
u8 is_connected;
std::array<u8, UserNameBytesMax + 1> user_name;
- INSERT_PADDING_BYTES(0x1); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x1); // Reserved
s16 local_communication_version;
- INSERT_PADDING_BYTES(0x10); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x10); // Reserved
};
static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
@@ -232,14 +245,14 @@ struct LdnNetworkInfo {
SecurityMode security_mode;
AcceptPolicy station_accept_policy;
u8 has_action_frame;
- INSERT_PADDING_BYTES(0x2); // Padding
+ INSERT_PADDING_BYTES_NOINIT(0x2); // Padding
u8 node_count_max;
u8 node_count;
std::array<NodeInfo, NodeCountMax> nodes;
- INSERT_PADDING_BYTES(0x2); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
u16 advertise_data_size;
std::array<u8, AdvertiseDataSizeMax> advertise_data;
- INSERT_PADDING_BYTES(0x8C); // Reserved
+ INSERT_PADDING_BYTES_NOINIT(0x8C); // Reserved
u64 random_authentication_id;
};
static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
@@ -250,6 +263,7 @@ struct NetworkInfo {
LdnNetworkInfo ldn;
};
static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
+static_assert(std::is_trivial_v<NetworkInfo>, "NetworkInfo type must be trivially copyable.");
struct SecurityConfig {
SecurityMode security_mode;
@@ -303,4 +317,36 @@ struct AddressList {
};
static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
+struct GroupInfo {
+ std::array<u8, 0x200> info;
+};
+
+struct CreateNetworkConfig {
+ SecurityConfig security_config;
+ UserConfig user_config;
+ INSERT_PADDING_BYTES(0x4);
+ NetworkConfig network_config;
+};
+static_assert(sizeof(CreateNetworkConfig) == 0x98, "CreateNetworkConfig is an invalid size");
+
+#pragma pack(push, 4)
+struct CreateNetworkConfigPrivate {
+ SecurityConfig security_config;
+ SecurityParameter security_parameter;
+ UserConfig user_config;
+ INSERT_PADDING_BYTES(0x4);
+ NetworkConfig network_config;
+};
+#pragma pack(pop)
+static_assert(sizeof(CreateNetworkConfigPrivate) == 0xB8,
+ "CreateNetworkConfigPrivate is an invalid size");
+
+struct ConnectNetworkData {
+ SecurityConfig security_config;
+ UserConfig user_config;
+ s32 local_communication_version;
+ ConnectOption option;
+};
+static_assert(sizeof(ConnectNetworkData) == 0x7c, "ConnectNetworkData is an invalid size");
+
} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/monitor_service.cpp b/src/core/hle/service/ldn/monitor_service.cpp
new file mode 100644
index 000000000..3471f69da
--- /dev/null
+++ b/src/core/hle/service/ldn/monitor_service.cpp
@@ -0,0 +1,43 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ldn/monitor_service.h"
+
+namespace Service::LDN {
+
+IMonitorService::IMonitorService(Core::System& system_)
+ : ServiceFramework{system_, "IMonitorService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IMonitorService::GetStateForMonitor>, "GetStateForMonitor"},
+ {1, nullptr, "GetNetworkInfoForMonitor"},
+ {2, nullptr, "GetIpv4AddressForMonitor"},
+ {3, nullptr, "GetDisconnectReasonForMonitor"},
+ {4, nullptr, "GetSecurityParameterForMonitor"},
+ {5, nullptr, "GetNetworkConfigForMonitor"},
+ {100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"},
+ {101, nullptr, "FinalizeMonitor"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IMonitorService::~IMonitorService() = default;
+
+Result IMonitorService::GetStateForMonitor(Out<State> out_state) {
+ LOG_INFO(Service_LDN, "called");
+
+ *out_state = state;
+ R_SUCCEED();
+}
+
+Result IMonitorService::InitializeMonitor() {
+ LOG_INFO(Service_LDN, "called");
+
+ state = State::Initialized;
+ R_SUCCEED();
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/monitor_service.h b/src/core/hle/service/ldn/monitor_service.h
new file mode 100644
index 000000000..61aacef30
--- /dev/null
+++ b/src/core/hle/service/ldn/monitor_service.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::LDN {
+
+class IMonitorService final : public ServiceFramework<IMonitorService> {
+public:
+ explicit IMonitorService(Core::System& system_);
+ ~IMonitorService() override;
+
+private:
+ Result GetStateForMonitor(Out<State> out_state);
+ Result InitializeMonitor();
+
+ State state{State::None};
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_monitor_service.cpp b/src/core/hle/service/ldn/sf_monitor_service.cpp
new file mode 100644
index 000000000..9e6736ff2
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_monitor_service.cpp
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/ldn/sf_monitor_service.h"
+
+namespace Service::LDN {
+
+ISfMonitorService::ISfMonitorService(Core::System& system_)
+ : ServiceFramework{system_, "ISfMonitorService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&ISfMonitorService::Initialize>, "Initialize"},
+ {288, C<&ISfMonitorService::GetGroupInfo>, "GetGroupInfo"},
+ {320, nullptr, "GetLinkLevel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISfMonitorService::~ISfMonitorService() = default;
+
+Result ISfMonitorService::Initialize(Out<u32> out_value) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+ *out_value = 0;
+ R_SUCCEED();
+}
+
+Result ISfMonitorService::GetGroupInfo(
+ OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+ *out_group_info = GroupInfo{};
+ R_SUCCEED();
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_monitor_service.h b/src/core/hle/service/ldn/sf_monitor_service.h
new file mode 100644
index 000000000..d02115201
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_monitor_service.h
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::LDN {
+struct GroupInfo;
+
+class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
+public:
+ explicit ISfMonitorService(Core::System& system_);
+ ~ISfMonitorService() override;
+
+private:
+ Result Initialize(Out<u32> out_value);
+ Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service.cpp b/src/core/hle/service/ldn/sf_service.cpp
new file mode 100644
index 000000000..61cabe219
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service.cpp
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/ldn/sf_service.h"
+
+namespace Service::LDN {
+
+ISfService::ISfService(Core::System& system_) : ServiceFramework{system_, "ISfService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
+ {264, nullptr, "GetNetworkInterfaceLastError"},
+ {272, nullptr, "GetRole"},
+ {280, nullptr, "GetAdvertiseData"},
+ {288, nullptr, "GetGroupInfo"},
+ {296, nullptr, "GetGroupInfo2"},
+ {304, nullptr, "GetGroupOwner"},
+ {312, nullptr, "GetIpConfig"},
+ {320, nullptr, "GetLinkLevel"},
+ {512, nullptr, "Scan"},
+ {768, nullptr, "CreateGroup"},
+ {776, nullptr, "DestroyGroup"},
+ {784, nullptr, "SetAdvertiseData"},
+ {1536, nullptr, "SendToOtherGroup"},
+ {1544, nullptr, "RecvFromOtherGroup"},
+ {1552, nullptr, "AddAcceptableGroupId"},
+ {1560, nullptr, "ClearAcceptableGroupId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISfService::~ISfService() = default;
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service.h b/src/core/hle/service/ldn/sf_service.h
new file mode 100644
index 000000000..05534b567
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::LDN {
+
+class ISfService final : public ServiceFramework<ISfService> {
+public:
+ explicit ISfService(Core::System& system_);
+ ~ISfService() override;
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service_monitor.cpp b/src/core/hle/service/ldn/sf_service_monitor.cpp
new file mode 100644
index 000000000..33e3c1d69
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service_monitor.cpp
@@ -0,0 +1,50 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/ldn/sf_service_monitor.h"
+
+namespace Service::LDN {
+
+ISfServiceMonitor::ISfServiceMonitor(Core::System& system_)
+ : ServiceFramework{system_, "ISfServiceMonitor"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&ISfServiceMonitor::Initialize>, "Initialize"},
+ {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
+ {264, nullptr, "GetNetworkInterfaceLastError"},
+ {272, nullptr, "GetRole"},
+ {280, nullptr, "GetAdvertiseData"},
+ {281, nullptr, "GetAdvertiseData2"},
+ {288, C<&ISfServiceMonitor::GetGroupInfo>, "GetGroupInfo"},
+ {296, nullptr, "GetGroupInfo2"},
+ {304, nullptr, "GetGroupOwner"},
+ {312, nullptr, "GetIpConfig"},
+ {320, nullptr, "GetLinkLevel"},
+ {328, nullptr, "AttachJoinEvent"},
+ {336, nullptr, "GetMembers"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISfServiceMonitor::~ISfServiceMonitor() = default;
+
+Result ISfServiceMonitor::Initialize(Out<u32> out_value) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+ *out_value = 0;
+ R_SUCCEED();
+}
+
+Result ISfServiceMonitor::GetGroupInfo(
+ OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+ *out_group_info = GroupInfo{};
+ R_SUCCEED();
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service_monitor.h b/src/core/hle/service/ldn/sf_service_monitor.h
new file mode 100644
index 000000000..3cfc5005e
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service_monitor.h
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::LDN {
+struct GroupInfo;
+
+class ISfServiceMonitor final : public ServiceFramework<ISfServiceMonitor> {
+public:
+ explicit ISfServiceMonitor(Core::System& system_);
+ ~ISfServiceMonitor() override;
+
+private:
+ Result Initialize(Out<u32> out_value);
+ Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/system_local_communication_service.cpp b/src/core/hle/service/ldn/system_local_communication_service.cpp
new file mode 100644
index 000000000..7b52223cd
--- /dev/null
+++ b/src/core/hle/service/ldn/system_local_communication_service.cpp
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ldn/system_local_communication_service.h"
+
+namespace Service::LDN {
+
+ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System& system_)
+ : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "GetNetworkInfo"},
+ {2, nullptr, "GetIpv4Address"},
+ {3, nullptr, "GetDisconnectReason"},
+ {4, nullptr, "GetSecurityParameter"},
+ {5, nullptr, "GetNetworkConfig"},
+ {100, nullptr, "AttachStateChangeEvent"},
+ {101, nullptr, "GetNetworkInfoLatestUpdate"},
+ {102, nullptr, "Scan"},
+ {103, nullptr, "ScanPrivate"},
+ {104, nullptr, "SetWirelessControllerRestriction"},
+ {200, nullptr, "OpenAccessPoint"},
+ {201, nullptr, "CloseAccessPoint"},
+ {202, nullptr, "CreateNetwork"},
+ {203, nullptr, "CreateNetworkPrivate"},
+ {204, nullptr, "DestroyNetwork"},
+ {205, nullptr, "Reject"},
+ {206, nullptr, "SetAdvertiseData"},
+ {207, nullptr, "SetStationAcceptPolicy"},
+ {208, nullptr, "AddAcceptFilterEntry"},
+ {209, nullptr, "ClearAcceptFilter"},
+ {300, nullptr, "OpenStation"},
+ {301, nullptr, "CloseStation"},
+ {302, nullptr, "Connect"},
+ {303, nullptr, "ConnectPrivate"},
+ {304, nullptr, "Disconnect"},
+ {400, nullptr, "InitializeSystem"},
+ {401, nullptr, "FinalizeSystem"},
+ {402, nullptr, "SetOperationMode"},
+ {403, C<&ISystemLocalCommunicationService::InitializeSystem2>, "InitializeSystem2"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemLocalCommunicationService::~ISystemLocalCommunicationService() = default;
+
+Result ISystemLocalCommunicationService::InitializeSystem2() {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/system_local_communication_service.h b/src/core/hle/service/ldn/system_local_communication_service.h
new file mode 100644
index 000000000..a02b097ea
--- /dev/null
+++ b/src/core/hle/service/ldn/system_local_communication_service.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::LDN {
+
+class ISystemLocalCommunicationService final
+ : public ServiceFramework<ISystemLocalCommunicationService> {
+public:
+ explicit ISystemLocalCommunicationService(Core::System& system_);
+ ~ISystemLocalCommunicationService() override;
+
+private:
+ Result InitializeSystem2();
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp
new file mode 100644
index 000000000..f28368962
--- /dev/null
+++ b/src/core/hle/service/ldn/user_local_communication_service.cpp
@@ -0,0 +1,320 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include <memory>
+
+#include "core/core.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ldn/ldn_results.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/ldn/user_local_communication_service.h"
+#include "core/hle/service/server_manager.h"
+#include "core/internal_network/network.h"
+#include "core/internal_network/network_interface.h"
+#include "network/network.h"
+
+// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
+#undef CreateEvent
+
+namespace Service::LDN {
+
+IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
+ : ServiceFramework{system_, "IUserLocalCommunicationService"},
+ service_context{system, "IUserLocalCommunicationService"},
+ room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, C<&IUserLocalCommunicationService::GetState>, "GetState"},
+ {1, C<&IUserLocalCommunicationService::GetNetworkInfo>, "GetNetworkInfo"},
+ {2, C<&IUserLocalCommunicationService::GetIpv4Address>, "GetIpv4Address"},
+ {3, C<&IUserLocalCommunicationService::GetDisconnectReason>, "GetDisconnectReason"},
+ {4, C<&IUserLocalCommunicationService::GetSecurityParameter>, "GetSecurityParameter"},
+ {5, C<&IUserLocalCommunicationService::GetNetworkConfig>, "GetNetworkConfig"},
+ {100, C<&IUserLocalCommunicationService::AttachStateChangeEvent>, "AttachStateChangeEvent"},
+ {101, C<&IUserLocalCommunicationService::GetNetworkInfoLatestUpdate>, "GetNetworkInfoLatestUpdate"},
+ {102, C<&IUserLocalCommunicationService::Scan>, "Scan"},
+ {103, C<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
+ {104, C<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
+ {200, C<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
+ {201, C<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
+ {202, C<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
+ {203, C<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"},
+ {204, C<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"},
+ {205, nullptr, "Reject"},
+ {206, C<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"},
+ {207, C<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"},
+ {208, C<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"},
+ {209, nullptr, "ClearAcceptFilter"},
+ {300, C<&IUserLocalCommunicationService::OpenStation>, "OpenStation"},
+ {301, C<&IUserLocalCommunicationService::CloseStation>, "CloseStation"},
+ {302, C<&IUserLocalCommunicationService::Connect>, "Connect"},
+ {303, nullptr, "ConnectPrivate"},
+ {304, C<&IUserLocalCommunicationService::Disconnect>, "Disconnect"},
+ {400, C<&IUserLocalCommunicationService::Initialize>, "Initialize"},
+ {401, C<&IUserLocalCommunicationService::Finalize>, "Finalize"},
+ {402, C<&IUserLocalCommunicationService::Initialize2>, "Initialize2"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ state_change_event =
+ service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
+}
+
+IUserLocalCommunicationService::~IUserLocalCommunicationService() {
+ if (is_initialized) {
+ if (auto room_member = room_network.GetRoomMember().lock()) {
+ room_member->Unbind(ldn_packet_received);
+ }
+ }
+
+ service_context.CloseEvent(state_change_event);
+}
+
+Result IUserLocalCommunicationService::GetState(Out<State> out_state) {
+ *out_state = State::Error;
+
+ if (is_initialized) {
+ *out_state = lan_discovery.GetState();
+ }
+
+ LOG_INFO(Service_LDN, "called, state={}", *out_state);
+
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::GetNetworkInfo(
+ OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info) {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info));
+}
+
+Result IUserLocalCommunicationService::GetIpv4Address(Out<Ipv4Address> out_current_address,
+ Out<Ipv4Address> out_subnet_mask) {
+ LOG_INFO(Service_LDN, "called");
+ const auto network_interface = Network::GetSelectedNetworkInterface();
+
+ R_UNLESS(network_interface.has_value(), ResultNoIpAddress);
+
+ *out_current_address = {Network::TranslateIPv4(network_interface->ip_address)};
+ *out_subnet_mask = {Network::TranslateIPv4(network_interface->subnet_mask)};
+
+ // When we're connected to a room, spoof the hosts IP address
+ if (auto room_member = room_network.GetRoomMember().lock()) {
+ if (room_member->IsConnected()) {
+ *out_current_address = room_member->GetFakeIpAddress();
+ }
+ }
+
+ std::reverse(std::begin(*out_current_address), std::end(*out_current_address)); // ntohl
+ std::reverse(std::begin(*out_subnet_mask), std::end(*out_subnet_mask)); // ntohl
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::GetDisconnectReason(
+ Out<DisconnectReason> out_disconnect_reason) {
+ LOG_INFO(Service_LDN, "called");
+
+ *out_disconnect_reason = lan_discovery.GetDisconnectReason();
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::GetSecurityParameter(
+ Out<SecurityParameter> out_security_parameter) {
+ LOG_INFO(Service_LDN, "called");
+
+ NetworkInfo info{};
+ R_TRY(lan_discovery.GetNetworkInfo(info));
+
+ out_security_parameter->session_id = info.network_id.session_id;
+ std::memcpy(out_security_parameter->data.data(), info.ldn.security_parameter.data(),
+ sizeof(SecurityParameter::data));
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::GetNetworkConfig(Out<NetworkConfig> out_network_config) {
+ LOG_INFO(Service_LDN, "called");
+
+ NetworkInfo info{};
+ R_TRY(lan_discovery.GetNetworkInfo(info));
+
+ out_network_config->intent_id = info.network_id.intent_id;
+ out_network_config->channel = info.common.channel;
+ out_network_config->node_count_max = info.ldn.node_count_max;
+ out_network_config->local_communication_version = info.ldn.nodes[0].local_communication_version;
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::AttachStateChangeEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_LDN, "called");
+
+ *out_event = &state_change_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(
+ OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
+ OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update) {
+ LOG_INFO(Service_LDN, "called");
+
+ R_UNLESS(!out_node_latest_update.empty(), ResultBadInput);
+
+ R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info, out_node_latest_update));
+}
+
+Result IUserLocalCommunicationService::Scan(
+ Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
+ OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
+ LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
+ channel, scan_filter.flag, scan_filter.network_type);
+
+ R_UNLESS(!out_network_info.empty(), ResultBadInput);
+ R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
+}
+
+Result IUserLocalCommunicationService::ScanPrivate(
+ Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
+ OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
+ LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
+ channel, scan_filter.flag, scan_filter.network_type);
+
+ R_UNLESS(out_network_info.empty(), ResultBadInput);
+ R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
+}
+
+Result IUserLocalCommunicationService::SetWirelessControllerRestriction(
+ WirelessControllerRestriction wireless_restriction) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::OpenAccessPoint() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.OpenAccessPoint());
+}
+
+Result IUserLocalCommunicationService::CloseAccessPoint() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.CloseAccessPoint());
+}
+
+Result IUserLocalCommunicationService::CreateNetwork(const CreateNetworkConfig& create_config) {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
+ create_config.network_config));
+}
+
+Result IUserLocalCommunicationService::CreateNetworkPrivate(
+ const CreateNetworkConfigPrivate& create_config,
+ InArray<AddressEntry, BufferAttr_HipcPointer> address_list) {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
+ create_config.network_config));
+}
+
+Result IUserLocalCommunicationService::DestroyNetwork() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.DestroyNetwork());
+}
+
+Result IUserLocalCommunicationService::SetAdvertiseData(
+ InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.SetAdvertiseData(buffer_data));
+}
+
+Result IUserLocalCommunicationService::SetStationAcceptPolicy(AcceptPolicy accept_policy) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_address) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::OpenStation() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.OpenStation());
+}
+
+Result IUserLocalCommunicationService::CloseStation() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.CloseStation());
+}
+
+Result IUserLocalCommunicationService::Connect(
+ const ConnectNetworkData& connect_data,
+ InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info) {
+ LOG_INFO(Service_LDN,
+ "called, passphrase_size={}, security_mode={}, "
+ "local_communication_version={}",
+ connect_data.security_config.passphrase_size,
+ connect_data.security_config.security_mode, connect_data.local_communication_version);
+
+ R_RETURN(lan_discovery.Connect(*network_info, connect_data.user_config,
+ static_cast<u16>(connect_data.local_communication_version)));
+}
+
+Result IUserLocalCommunicationService::Disconnect() {
+ LOG_INFO(Service_LDN, "called");
+
+ R_RETURN(lan_discovery.Disconnect());
+}
+
+Result IUserLocalCommunicationService::Initialize(ClientProcessId aruid) {
+ LOG_INFO(Service_LDN, "called, process_id={}", aruid.pid);
+
+ const auto network_interface = Network::GetSelectedNetworkInterface();
+ R_UNLESS(network_interface, ResultAirplaneModeEnabled);
+
+ if (auto room_member = room_network.GetRoomMember().lock()) {
+ ldn_packet_received = room_member->BindOnLdnPacketReceived(
+ [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
+ } else {
+ LOG_ERROR(Service_LDN, "Couldn't bind callback!");
+ R_RETURN(ResultAirplaneModeEnabled);
+ }
+
+ lan_discovery.Initialize([&]() { OnEventFired(); });
+ is_initialized = true;
+ R_SUCCEED();
+}
+
+Result IUserLocalCommunicationService::Finalize() {
+ LOG_INFO(Service_LDN, "called");
+ if (auto room_member = room_network.GetRoomMember().lock()) {
+ room_member->Unbind(ldn_packet_received);
+ }
+
+ is_initialized = false;
+
+ R_RETURN(lan_discovery.Finalize());
+}
+
+Result IUserLocalCommunicationService::Initialize2(u32 version, ClientProcessId process_id) {
+ LOG_INFO(Service_LDN, "called, version={}, process_id={}", version, process_id.pid);
+ R_RETURN(Initialize(process_id));
+}
+
+void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacket& packet) {
+ lan_discovery.ReceivePacket(packet);
+}
+
+void IUserLocalCommunicationService::OnEventFired() {
+ state_change_event->Signal();
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/user_local_communication_service.h b/src/core/hle/service/ldn/user_local_communication_service.h
new file mode 100644
index 000000000..6698d10d2
--- /dev/null
+++ b/src/core/hle/service/ldn/user_local_communication_service.h
@@ -0,0 +1,103 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/ldn/lan_discovery.h"
+#include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Network {
+class RoomNetwork;
+}
+
+namespace Service::LDN {
+
+class IUserLocalCommunicationService final
+ : public ServiceFramework<IUserLocalCommunicationService> {
+public:
+ explicit IUserLocalCommunicationService(Core::System& system_);
+ ~IUserLocalCommunicationService() override;
+
+private:
+ Result GetState(Out<State> out_state);
+
+ Result GetNetworkInfo(OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info);
+
+ Result GetIpv4Address(Out<Ipv4Address> out_current_address, Out<Ipv4Address> out_subnet_mask);
+
+ Result GetDisconnectReason(Out<DisconnectReason> out_disconnect_reason);
+
+ Result GetSecurityParameter(Out<SecurityParameter> out_security_parameter);
+
+ Result GetNetworkConfig(Out<NetworkConfig> out_network_config);
+
+ Result AttachStateChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+ Result GetNetworkInfoLatestUpdate(
+ OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
+ OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update);
+
+ Result Scan(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
+ OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
+
+ Result ScanPrivate(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
+ OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
+
+ Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction);
+
+ Result OpenAccessPoint();
+
+ Result CloseAccessPoint();
+
+ Result CreateNetwork(const CreateNetworkConfig& create_network_Config);
+
+ Result CreateNetworkPrivate(const CreateNetworkConfigPrivate& create_network_Config,
+ InArray<AddressEntry, BufferAttr_HipcPointer> address_list);
+
+ Result DestroyNetwork();
+
+ Result SetAdvertiseData(InBuffer<BufferAttr_HipcAutoSelect> buffer_data);
+
+ Result SetStationAcceptPolicy(AcceptPolicy accept_policy);
+
+ Result AddAcceptFilterEntry(MacAddress mac_address);
+
+ Result OpenStation();
+
+ Result CloseStation();
+
+ Result Connect(const ConnectNetworkData& connect_data,
+ InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info);
+
+ Result Disconnect();
+
+ Result Initialize(ClientProcessId aruid);
+
+ Result Finalize();
+
+ Result Initialize2(u32 version, ClientProcessId aruid);
+
+private:
+ /// Callback to parse and handle a received LDN packet.
+ void OnLDNPacketReceived(const Network::LDNPacket& packet);
+ void OnEventFired();
+
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* state_change_event;
+ Network::RoomNetwork& room_network;
+ LANDiscovery lan_discovery;
+
+ // Callback identifier for the OnLDNPacketReceived event.
+ Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
+
+ bool is_initialized{};
+};
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 0086f82c5..adaaea571 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -207,7 +207,8 @@ private:
Result DestroyFile() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
@@ -217,7 +218,8 @@ private:
Result DeleteFile() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
@@ -227,7 +229,8 @@ private:
Result Format() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
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..7a91727f9
--- /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,
+ u32 flags, u64 application_id, Uid account_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}",
+ flags, application_id, account_id.uuid.FormattedString());
+
+ if (!out_rights.empty()) {
+ ApplicationRightsOnClient rights{};
+ rights.application_id = application_id;
+ rights.uid = account_id.uuid;
+ 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..f33d269b3
--- /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,
+ u32 flags, u64 application_id, Uid account_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/iplatform_service_manager.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp
deleted file mode 100644
index 46268be95..000000000
--- a/src/core/hle/service/ns/iplatform_service_manager.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <algorithm>
-#include <cstring>
-#include <vector>
-
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "common/swap.h"
-#include "core/core.h"
-#include "core/file_sys/content_archive.h"
-#include "core/file_sys/nca_metadata.h"
-#include "core/file_sys/registered_cache.h"
-#include "core/file_sys/romfs.h"
-#include "core/file_sys/system_archive/system_archive.h"
-#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/filesystem/filesystem.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
-
-namespace Service::NS {
-
-struct FontRegion {
- u32 offset;
- u32 size;
-};
-
-// The below data is specific to shared font data dumped from Switch on f/w 2.2
-// Virtual address and offsets/sizes likely will vary by dump
-[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
-constexpr u32 EXPECTED_RESULT{0x7f9a0218}; // What we expect the decrypted bfttf first 4 bytes to be
-constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf first 4 bytes to be
-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,
- "Shared fonts exceeds 17mb!");
- ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
-
- const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
- std::vector<u32> transformed_font(input.size());
- // TODO(ogniK): Figure out a better way to do this
- std::transform(input.begin(), input.end(), transformed_font.begin(),
- [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
- transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size
- std::memcpy(output.data() + offset, transformed_font.data(),
- transformed_font.size() * sizeof(u32));
- offset += transformed_font.size() * sizeof(u32);
-}
-
-void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
- ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
-
- if (input.size() < 2) {
- LOG_ERROR(Service_NS, "Input font is empty");
- return;
- }
-
- const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
- std::vector<u32> transformed_font(input.size());
- // TODO(ogniK): Figure out a better way to do this
- std::transform(input.begin(), input.end(), transformed_font.begin(),
- [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
- std::memcpy(output.data(), transformed_font.data() + 2,
- (transformed_font.size() - 2) * sizeof(u32));
-}
-
-void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
- std::size_t& offset) {
- ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
- "Shared fonts exceeds 17mb!");
-
- const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC);
- std::vector<u32> transformed_font(input.size() + 2);
- transformed_font[0] = Common::swap32(EXPECTED_MAGIC);
- transformed_font[1] = Common::swap32(static_cast<u32>(input.size() * sizeof(u32))) ^ key;
- std::transform(input.begin(), input.end(), transformed_font.begin() + 2,
- [key](u32 in) { return in ^ key; });
- std::memcpy(output.data() + offset, transformed_font.data(),
- transformed_font.size() * sizeof(u32));
- offset += transformed_font.size() * sizeof(u32);
-}
-
-// Helper function to make BuildSharedFontsRawRegions a bit nicer
-static u32 GetU32Swapped(const u8* data) {
- u32 value;
- std::memcpy(&value, data, sizeof(value));
- return Common::swap32(value);
-}
-
-struct IPlatformServiceManager::Impl {
- const FontRegion& GetSharedFontRegion(std::size_t index) const {
- if (index >= shared_font_regions.size() || shared_font_regions.empty()) {
- // No font fallback
- return EMPTY_REGION;
- }
- return shared_font_regions.at(index);
- }
-
- void BuildSharedFontsRawRegions(const Kernel::PhysicalMemory& input) {
- // As we can derive the xor key we can just populate the offsets
- // based on the shared memory dump
- unsigned cur_offset = 0;
-
- for (std::size_t i = 0; i < SHARED_FONTS.size(); i++) {
- // Out of shared fonts/invalid font
- if (GetU32Swapped(input.data() + cur_offset) != EXPECTED_RESULT) {
- break;
- }
-
- // Derive key within inverse xor
- const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC;
- const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY;
- shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE});
- cur_offset += SIZE + 8;
- }
- }
-
- /// Backing memory for the shared font data
- std::shared_ptr<Kernel::PhysicalMemory> shared_font;
-
- // Automatically populated based on shared_fonts dump or system archives.
- std::vector<FontRegion> shared_font_regions;
-};
-
-IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_)
- : 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"},
- {100, nullptr, "RequestApplicationFunctionAuthorization"},
- {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
- {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
- {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"},
- {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"},
- {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"},
- {106, nullptr, "GetFunctionBlackListVersion"},
- {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
- {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
- };
- // clang-format on
- RegisterHandlers(functions);
-
- auto& fsc = system.GetFileSystemController();
-
- // Attempt to load shared font data from disk
- const auto* nand = fsc.GetSystemNANDContents();
- std::size_t offset = 0;
- // Rebuild shared fonts from data ncas or synthesize
-
- impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE);
- for (auto font : SHARED_FONTS) {
- FileSys::VirtualFile romfs;
- const auto nca =
- nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data);
- if (nca) {
- romfs = nca->GetRomFS();
- }
-
- if (!romfs) {
- romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first));
- }
-
- if (!romfs) {
- LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping", font.first);
- continue;
- }
-
- const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
- if (!extracted_romfs) {
- LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping", font.first);
- continue;
- }
- const auto font_fp = extracted_romfs->GetFile(font.second);
- if (!font_fp) {
- LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping", font.first, font.second);
- continue;
- }
- std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32));
- font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize());
- // We need to be BigEndian as u32s for the xor encryption
- std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
- Common::swap32);
- // Font offset and size do not account for the header
- const FontRegion region{static_cast<u32>(offset + 8),
- static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)};
- DecryptSharedFont(font_data_u32, *impl->shared_font, offset);
- impl->shared_font_regions.push_back(region);
- }
-}
-
-IPlatformServiceManager::~IPlatformServiceManager() = default;
-
-void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 shared_font_type{rp.Pop<u32>()};
- // 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);
-}
-
-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));
-}
-
-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);
-}
-
-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);
-}
-
-void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
- // Map backing memory for the font data
- LOG_DEBUG(Service_NS, "called");
-
- // Create shared font memory object
- 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());
-}
-
-void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) {
- // 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;
-
- // 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);
- }
-
- // 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));
-
- ctx.WriteBuffer(font_codes, 0);
- ctx.WriteBuffer(font_offsets, 1);
- ctx.WriteBuffer(font_sizes, 2);
-
- rb.Push(ResultSuccess);
- rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded
- rb.Push<u32>(static_cast<u32>(font_codes.size()));
-}
-
-} // namespace Service::NS
diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/iplatform_service_manager.h
deleted file mode 100644
index 03071e02b..000000000
--- a/src/core/hle/service/ns/iplatform_service_manager.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <vector>
-#include "core/hle/service/service.h"
-
-namespace Service {
-
-namespace FileSystem {
-class FileSystemController;
-} // namespace FileSystem
-
-namespace NS {
-
-enum class FontArchives : u64 {
- Extension = 0x0100000000000810,
- Standard = 0x0100000000000811,
- Korean = 0x0100000000000812,
- ChineseTraditional = 0x0100000000000813,
- ChineseSimple = 0x0100000000000814,
-};
-
-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"),
- std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"),
- std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"),
- std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"),
- std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"),
- std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"),
-};
-
-void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output);
-void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
-
-class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> {
-public:
- explicit IPlatformServiceManager(Core::System& system_, const char* service_name_);
- ~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);
-
- struct Impl;
- std::unique_ptr<Impl> impl;
-};
-
-} // namespace NS
-
-} // namespace Service
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..2dd664c4e
--- /dev/null
+++ b/src/core/hle/service/ns/ns_types.h
@@ -0,0 +1,116 @@
+// 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.");
+
+struct Uid {
+ alignas(8) Common::UUID uuid;
+};
+static_assert(sizeof(Uid) == 0x10, "Uid 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/pdm_qry.h b/src/core/hle/service/ns/pdm_qry.h
deleted file mode 100644
index c98e01660..000000000
--- a/src/core/hle/service/ns/pdm_qry.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Service::NS {
-
-struct PlayStatistics {
- u64 application_id{};
- u32 first_entry_index{};
- u32 first_timestamp_user{};
- u32 first_timestamp_network{};
- u32 last_entry_index{};
- u32 last_timestamp_user{};
- u32 last_timestamp_network{};
- u32 play_time_in_minutes{};
- u32 total_launches{};
-};
-static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
-
-class PDM_QRY final : public ServiceFramework<PDM_QRY> {
-public:
- explicit PDM_QRY(Core::System& system_);
- ~PDM_QRY() override;
-
-private:
- void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx);
-};
-
-} // namespace Service::NS
diff --git a/src/core/hle/service/ns/platform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp
new file mode 100644
index 000000000..23cf05005
--- /dev/null
+++ b/src/core/hle/service/ns/platform_service_manager.cpp
@@ -0,0 +1,273 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <algorithm>
+#include <cstring>
+#include <vector>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "common/swap.h"
+#include "core/core.h"
+#include "core/file_sys/content_archive.h"
+#include "core/file_sys/nca_metadata.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/romfs.h"
+#include "core/file_sys/system_archive/system_archive.h"
+#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/ns/platform_service_manager.h"
+
+namespace Service::NS {
+
+struct FontRegion {
+ u32 offset;
+ u32 size;
+};
+
+// The below data is specific to shared font data dumped from Switch on f/w 2.2
+// Virtual address and offsets/sizes likely will vary by dump
+[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
+constexpr u32 EXPECTED_RESULT{0x7f9a0218}; // What we expect the decrypted bfttf first 4 bytes to be
+constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf first 4 bytes to be
+constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};
+constexpr FontRegion EMPTY_REGION{0, 0};
+
+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,
+ "Shared fonts exceeds 17mb!");
+ ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
+
+ const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
+ std::vector<u32> transformed_font(input.size());
+ // TODO(ogniK): Figure out a better way to do this
+ std::transform(input.begin(), input.end(), transformed_font.begin(),
+ [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
+ transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size
+ std::memcpy(output.data() + offset, transformed_font.data(),
+ transformed_font.size() * sizeof(u32));
+ offset += transformed_font.size() * sizeof(u32);
+}
+
+void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
+ ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
+
+ if (input.size() < 2) {
+ LOG_ERROR(Service_NS, "Input font is empty");
+ return;
+ }
+
+ const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
+ std::vector<u32> transformed_font(input.size());
+ // TODO(ogniK): Figure out a better way to do this
+ std::transform(input.begin(), input.end(), transformed_font.begin(),
+ [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
+ std::memcpy(output.data(), transformed_font.data() + 2,
+ (transformed_font.size() - 2) * sizeof(u32));
+}
+
+void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
+ std::size_t& offset) {
+ ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
+ "Shared fonts exceeds 17mb!");
+
+ const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC);
+ std::vector<u32> transformed_font(input.size() + 2);
+ transformed_font[0] = Common::swap32(EXPECTED_MAGIC);
+ transformed_font[1] = Common::swap32(static_cast<u32>(input.size() * sizeof(u32))) ^ key;
+ std::transform(input.begin(), input.end(), transformed_font.begin() + 2,
+ [key](u32 in) { return in ^ key; });
+ std::memcpy(output.data() + offset, transformed_font.data(),
+ transformed_font.size() * sizeof(u32));
+ offset += transformed_font.size() * sizeof(u32);
+}
+
+// Helper function to make BuildSharedFontsRawRegions a bit nicer
+static u32 GetU32Swapped(const u8* data) {
+ u32 value;
+ std::memcpy(&value, data, sizeof(value));
+ return Common::swap32(value);
+}
+
+struct IPlatformServiceManager::Impl {
+ const FontRegion& GetSharedFontRegion(std::size_t index) const {
+ if (index >= shared_font_regions.size() || shared_font_regions.empty()) {
+ // No font fallback
+ return EMPTY_REGION;
+ }
+ return shared_font_regions.at(index);
+ }
+
+ void BuildSharedFontsRawRegions(const Kernel::PhysicalMemory& input) {
+ // As we can derive the xor key we can just populate the offsets
+ // based on the shared memory dump
+ unsigned cur_offset = 0;
+
+ for (std::size_t i = 0; i < SHARED_FONTS.size(); i++) {
+ // Out of shared fonts/invalid font
+ if (GetU32Swapped(input.data() + cur_offset) != EXPECTED_RESULT) {
+ break;
+ }
+
+ // Derive key within inverse xor
+ const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC;
+ const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY;
+ shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE});
+ cur_offset += SIZE + 8;
+ }
+ }
+
+ /// Backing memory for the shared font data
+ std::shared_ptr<Kernel::PhysicalMemory> shared_font;
+
+ // Automatically populated based on shared_fonts dump or system archives.
+ std::vector<FontRegion> shared_font_regions;
+};
+
+IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_)
+ : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {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"},
+ {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"},
+ {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"},
+ {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"},
+ {106, nullptr, "GetFunctionBlackListVersion"},
+ {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
+ {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+
+ auto& fsc = system.GetFileSystemController();
+
+ // Attempt to load shared font data from disk
+ const auto* nand = fsc.GetSystemNANDContents();
+ std::size_t offset = 0;
+ // Rebuild shared fonts from data ncas or synthesize
+
+ impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE);
+ for (auto font : SHARED_FONTS) {
+ FileSys::VirtualFile romfs;
+ const auto nca =
+ nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data);
+ if (nca) {
+ romfs = nca->GetRomFS();
+ }
+
+ if (!romfs) {
+ romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first));
+ }
+
+ if (!romfs) {
+ LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping", font.first);
+ continue;
+ }
+
+ const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
+ if (!extracted_romfs) {
+ LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping", font.first);
+ continue;
+ }
+ const auto font_fp = extracted_romfs->GetFile(font.second);
+ if (!font_fp) {
+ LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping", font.first, font.second);
+ continue;
+ }
+ std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32));
+ font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize());
+ // We need to be BigEndian as u32s for the xor encryption
+ std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
+ Common::swap32);
+ // Font offset and size do not account for the header
+ const FontRegion region{static_cast<u32>(offset + 8),
+ static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)};
+ DecryptSharedFont(font_data_u32, *impl->shared_font, offset);
+ impl->shared_font_regions.push_back(region);
+ }
+}
+
+IPlatformServiceManager::~IPlatformServiceManager() = default;
+
+Result IPlatformServiceManager::RequestLoad(SharedFontType type) {
+ // Games don't call this so all fonts should be loaded
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ R_SUCCEED();
+}
+
+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();
+}
+
+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();
+}
+
+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();
+}
+
+Result IPlatformServiceManager::GetSharedMemoryNativeHandle(
+ OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) {
+ // Map backing memory for the font data
+ LOG_DEBUG(Service_NS, "called");
+
+ // Create shared font memory object
+ std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),
+ impl->shared_font->size());
+
+ // FIXME: this shouldn't belong to the kernel
+ *out_shared_memory_native_handle = &kernel.GetFontSharedMem();
+ R_SUCCEED();
+}
+
+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 size_t MaxElementCount = 6;
+
+ // TODO(ogniK): Have actual priority order
+ const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(),
+ out_font_sizes.size(), impl->shared_font_regions.size()});
+
+ for (size_t i = 0; i < max_size; i++) {
+ auto region = impl->GetSharedFontRegion(i);
+
+ out_font_codes[i] = static_cast<u32>(i);
+ out_font_offsets[i] = region.offset;
+ out_font_sizes[i] = region.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/platform_service_manager.h b/src/core/hle/service/ns/platform_service_manager.h
new file mode 100644
index 000000000..b82c385a6
--- /dev/null
+++ b/src/core/hle/service/ns/platform_service_manager.h
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#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 {
+
+namespace FileSystem {
+class FileSystemController;
+} // namespace FileSystem
+
+namespace NS {
+
+enum class FontArchives : u64 {
+ Extension = 0x0100000000000810,
+ Standard = 0x0100000000000811,
+ Korean = 0x0100000000000812,
+ ChineseTraditional = 0x0100000000000813,
+ 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"),
+ std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"),
+ std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"),
+ std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"),
+ std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"),
+ std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"),
+};
+
+void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output);
+void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
+
+class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> {
+public:
+ explicit IPlatformServiceManager(Core::System& system_, const char* service_name_);
+ ~IPlatformServiceManager() override;
+
+private:
+ 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;
+};
+
+} // namespace NS
+
+} // namespace Service
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..138400541
--- /dev/null
+++ b/src/core/hle/service/ns/query_service.cpp
@@ -0,0 +1,56 @@
+// 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, u64 application_id, Uid account_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.uuid.FormattedString());
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/query_service.h b/src/core/hle/service/ns/query_service.h
new file mode 100644
index 000000000..c4c82b752
--- /dev/null
+++ b/src/core/hle/service/ns/query_service.h
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/uuid.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+struct PlayStatistics {
+ u64 application_id{};
+ u32 first_entry_index{};
+ u32 first_timestamp_user{};
+ u32 first_timestamp_network{};
+ u32 last_entry_index{};
+ u32 last_timestamp_user{};
+ u32 last_timestamp_network{};
+ u32 play_time_in_minutes{};
+ u32 total_launches{};
+};
+static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
+
+class IQueryService final : public ServiceFramework<IQueryService> {
+public:
+ explicit IQueryService(Core::System& system_);
+ ~IQueryService() override;
+
+private:
+ Result QueryPlayStatisticsByApplicationIdAndUserAccountId(
+ Out<PlayStatistics> out_play_statistics, bool unknown, u64 application_id, Uid account_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 aef1477e3..124accb94 100644
--- a/src/core/hle/service/nvnflinger/binder.h
+++ b/src/core/hle/service/nvnflinger/binder.h
@@ -6,6 +6,8 @@
#pragma once
+#include <span>
+
#include "common/common_types.h"
namespace Kernel {
@@ -18,28 +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(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 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 5d8762d25..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,12 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
return Status::NoError;
}
-void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) {
+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{ctx.ReadBuffer()};
+ 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>();
@@ -917,11 +932,13 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
parcel_out.Write(status);
- ctx.WriteBuffer(parcel_out.Serialize());
+ const auto serialized = parcel_out.Serialize();
+ std::memcpy(parcel_reply.data(), serialized.data(),
+ 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 64c17d56c..048523514 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
@@ -45,11 +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(HLERequestContext& ctx, android::TransactionId code, u32 flags) 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..40aa59787
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/display.h
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#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::vector<std::shared_ptr<Layer>> layers;
+
+ std::shared_ptr<Layer> FindLayer(s32 consumer_id) {
+ for (auto& layer : layers) {
+ if (layer->consumer_id == consumer_id) {
+ return layer;
+ }
+ }
+
+ return nullptr;
+ }
+
+ bool HasLayers() {
+ return !layers.empty();
+ }
+};
+
+struct Display {
+ explicit Display(u64 id_) {
+ id = id_;
+ }
+
+ u64 id;
+ LayerStack stack;
+};
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
deleted file mode 100644
index 90f7248a0..000000000
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <random>
-
-#include "core/core.h"
-#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/k_system_resource.h"
-#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/vi_results.h"
-#include "video_core/gpu.h"
-#include "video_core/host1x/host1x.h"
-
-namespace Service::Nvnflinger {
-
-namespace {
-
-Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group,
- Core::System& system, u32 size) {
- 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.
- auto pg = std::make_unique<Kernel::KPageGroup>(
- kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager()));
-
- // Allocate memory from secure pool.
- R_TRY(kernel.MemoryManager().AllocateAndOpen(
- pg.get(), size / YUZU_PAGESIZE,
- Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
- Kernel::KMemoryManager::Direction::FromBack)));
-
- // Fill the output data with red.
- for (auto& block : *pg) {
- u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
- u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
-
- for (; start < end; start++) {
- *start = 0xFF0000FF;
- }
- }
-
- // Return the mapped page group.
- *out_page_group = std::move(pg);
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address,
- std::unique_ptr<Kernel::KPageGroup>& pg,
- Kernel::KProcess* process, Core::System& system) {
- using Core::Memory::YUZU_PAGESIZE;
-
- auto& page_table = process->GetPageTable();
-
- // Get bounds of where mapping is possible.
- const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());
- const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE;
- const auto state = Kernel::KMemoryState::IoMemory;
- const auto perm = Kernel::KMemoryPermission::UserReadWrite;
- std::mt19937_64 rng{process->GetRandomEntropy(0)};
-
- // Retry up to 64 times to map into alias code range.
- Result res = ResultSuccess;
- int i;
- for (i = 0; i < 64; i++) {
- *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE);
- res = page_table.MapPageGroup(*out_map_address, *pg, state, perm);
- if (R_SUCCEEDED(res)) {
- break;
- }
- }
-
- // Return failure, if necessary
- R_UNLESS(i < 64, res);
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
- // Create a handle.
- Nvidia::Devices::nvmap::IocCreateParams create_params{
- .size = size,
- .handle = 0,
- };
- R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success,
- VI::ResultOperationFailed);
-
- // Assign the output handle.
- *out_nv_map_handle = create_params.handle;
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) {
- // Free the handle.
- Nvidia::Devices::nvmap::IocFreeParams free_params{
- .handle = handle,
- };
- R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success,
- VI::ResultOperationFailed);
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
- u32 size, Nvidia::DeviceFD nvmap_fd) {
- // Assign the allocated memory to the handle.
- Nvidia::Devices::nvmap::IocAllocParams alloc_params{
- .handle = handle,
- .heap_mask = 0,
- .flags = {},
- .align = 0,
- .kind = 0,
- .address = GetInteger(buffer),
- };
- R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success,
- VI::ResultOperationFailed);
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd,
- Common::ProcessAddress buffer, u32 size) {
- // Get the nvmap device.
- auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
- ASSERT(nvmap != nullptr);
-
- // Create a handle.
- R_TRY(CreateNvMapHandle(out_handle, *nvmap, size));
-
- // Ensure we maintain a clean state on failure.
- ON_RESULT_FAILURE {
- R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd));
- };
-
- // Assign the allocated memory to the handle.
- R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));
-}
-
-void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) {
- auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
- ASSERT(nvmap != nullptr);
-
- R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd));
-}
-
-constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
-constexpr u32 SharedBufferBlockLinearBpp = 4;
-
-constexpr u32 SharedBufferBlockLinearWidth = 1280;
-constexpr u32 SharedBufferBlockLinearHeight = 768;
-constexpr u32 SharedBufferBlockLinearStride =
- SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
-constexpr u32 SharedBufferNumSlots = 7;
-
-constexpr u32 SharedBufferWidth = 1280;
-constexpr u32 SharedBufferHeight = 720;
-constexpr u32 SharedBufferAsync = false;
-
-constexpr u32 SharedBufferSlotSize =
- SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp;
-constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots;
-
-constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
- SharedMemoryPoolLayout layout{};
- layout.num_slots = SharedBufferNumSlots;
-
- for (u32 i = 0; i < SharedBufferNumSlots; i++) {
- layout.slots[i].buffer_offset = i * SharedBufferSlotSize;
- layout.slots[i].size = SharedBufferSlotSize;
- layout.slots[i].width = SharedBufferWidth;
- layout.slots[i].height = SharedBufferHeight;
- }
-
- return layout;
-}();
-
-void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
- auto buffer = std::make_shared<android::NvGraphicBuffer>();
- buffer->width = SharedBufferWidth;
- buffer->height = SharedBufferHeight;
- buffer->stride = SharedBufferBlockLinearStride;
- buffer->format = SharedBufferBlockLinearFormat;
- buffer->external_format = SharedBufferBlockLinearFormat;
- buffer->buffer_id = handle;
- buffer->offset = slot * SharedBufferSlotSize;
- ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
-}
-
-} // 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)) {}
-
-FbShareBufferManager::~FbShareBufferManager() = default;
-
-Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id,
- u64* out_layer_handle, u64 display_id,
- LayerBlending blending) {
- std::scoped_lock lk{m_guard};
-
- // Ensure we haven't already created.
- const u64 aruid = owner_process->GetProcessId();
- R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
-
- // Allocate memory for the shared buffer if needed.
- if (!m_buffer_page_group) {
- R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
- SharedBufferSize));
-
- // Record buffer id.
- m_buffer_id = m_next_buffer_id++;
-
- // Record display id.
- m_display_id = display_id;
- }
-
- // Map into process.
- Common::ProcessAddress map_address{};
- R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
- owner_process, m_system));
-
- // Create new session.
- auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{});
- auto& session = it->second;
-
- auto& container = m_nvdrv->GetContainer();
- session.session_id = container.OpenSession(owner_process);
- session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
-
- // Create an nvmap handle for the buffer and assign the memory to it.
- R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
- 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);
-
- // Get the layer.
- VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id);
- ASSERT(layer != nullptr);
-
- // 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);
-
- // Assign outputs.
- *out_buffer_id = m_buffer_id;
- *out_layer_handle = session.layer_id;
-
- // We succeeded.
- R_SUCCEED();
-}
-
-void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
- std::scoped_lock lk{m_guard};
-
- if (m_buffer_id == 0) {
- return;
- }
-
- const u64 aruid = owner_process->GetProcessId();
- const auto it = m_sessions.find(aruid);
- if (it == m_sessions.end()) {
- return;
- }
-
- auto& session = it->second;
-
- // Destroy the layer.
- m_flinger.DestroyLayer(session.layer_id);
-
- // Close nvmap handle.
- FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
-
- // Close nvmap device.
- m_nvdrv->Close(session.nvmap_fd);
-
- // Close session.
- auto& container = m_nvdrv->GetContainer();
- container.CloseSession(session.session_id);
-
- // Erase.
- 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) {
- std::scoped_lock lk{m_guard};
-
- R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);
- R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound);
- R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound);
-
- *out_pool_layout = SharedBufferPoolLayout;
- *out_buffer_size = SharedBufferSize;
- *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle;
-
- 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) {
- 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();
-
- // 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,
- VI::ResultOperationFailed);
-
- // Assign remaining outputs.
- *out_target_slot = slot;
- out_slot_indexes = {0, 1, -1, -1};
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result FbShareBufferManager::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();
-
- // Request to queue the buffer.
- std::shared_ptr<android::GraphicBuffer> 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);
- };
-
- // Queue the buffer to the producer.
- android::QueueBufferInput input{};
- android::QueueBufferOutput output{};
- input.crop = crop_region;
- 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)) ==
- android::Status::NoError,
- VI::ResultOperationFailed);
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
- 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();
-
- // Set the event.
- *out_event = std::addressof(producer.GetNativeHandle());
-
- // We succeeded.
- R_SUCCEED();
-}
-
-Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
- std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
- Common::ScratchBuffer<u32> scratch;
-
- // TODO: this could be optimized
- s64 e = -1280 * 768 * 4;
- for (auto& block : *m_buffer_page_group) {
- u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
- u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
-
- for (; start < end; start++) {
- *start = 0;
-
- if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
- *start = capture_buffer[e];
- }
- e++;
- }
-
- m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
- m_system.GPU().InvalidateRegion(addr, end - start);
- });
- }
-
- *out_was_written = true;
- *out_layer_index = 1;
- R_SUCCEED();
-}
-
-} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
deleted file mode 100644
index b79a7d23a..000000000
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <map>
-
-#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;
-}
-
-namespace Service::Nvnflinger {
-
-struct SharedMemorySlot {
- u64 buffer_offset;
- u64 size;
- s32 width;
- s32 height;
-};
-static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size");
-
-struct SharedMemoryPoolLayout {
- s32 num_slots;
- std::array<SharedMemorySlot, 0x10> slots;
-};
-static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
-
-struct FbShareSession;
-
-class FbShareBufferManager final {
-public:
- explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
- std::shared_ptr<Nvidia::Module> nvdrv);
- ~FbShareBufferManager();
-
- 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 GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,
- SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,
- u64 applet_resource_user_id);
- Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots,
- 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 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::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;
-};
-
-struct FbShareSession {
- Nvidia::DeviceFD nvmap_fd = {};
- Nvidia::NvCore::SessionId session_id = {};
- u64 layer_id = {};
- u32 buffer_nvmap_handle = 0;
-};
-
-} // 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..f2dfe85a9 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.
@@ -135,10 +134,10 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
continue;
}
- if (auto* layer = display.FindLayer(layer_id); layer != nullptr) {
+ if (const auto layer = display.stack.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);
+ const auto layer = display.stack.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/nvnflinger/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
new file mode 100644
index 000000000..8629a2e89
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
@@ -0,0 +1,66 @@
+// 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/nvnflinger/binder.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+
+namespace Service::Nvnflinger {
+
+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"},
+ {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"},
+ {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"},
+ };
+ RegisterHandlers(functions);
+}
+
+IHOSBinderDriver::~IHOSBinderDriver() = default;
+
+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);
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_SUCCEED_IF(binder == nullptr);
+
+ binder->Transact(transaction_id, parcel_data, parcel_reply, flags);
+
+ R_SUCCEED();
+}
+
+Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {
+ LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type);
+ R_SUCCEED();
+}
+
+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);
+
+ 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, 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::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h
new file mode 100644
index 000000000..b7fb07bd2
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Nvnflinger {
+
+class HosBinderDriverServer;
+class SurfaceFlinger;
+
+class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
+public:
+ 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, 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, u32 transaction_id,
+ InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
+ OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags);
+
+private:
+ const std::shared_ptr<HosBinderDriverServer> m_server;
+ const std::shared_ptr<SurfaceFlinger> m_surface_flinger;
+};
+
+} // 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..8362b65e5
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp
@@ -0,0 +1,139 @@
+// 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->stack.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::CreateLayer(s32 consumer_binder_id) {
+ auto binder = std::static_pointer_cast<android::BufferQueueConsumer>(
+ m_server.TryGetBinder(consumer_binder_id));
+ if (!binder) {
+ return;
+ }
+
+ auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder));
+ buffer_item_consumer->Connect(false);
+
+ m_layers.layers.emplace_back(
+ std::make_shared<Layer>(std::move(buffer_item_consumer), consumer_binder_id));
+}
+
+void SurfaceFlinger::DestroyLayer(s32 consumer_binder_id) {
+ std::erase_if(m_layers.layers,
+ [&](auto& layer) { return layer->consumer_id == consumer_binder_id; });
+}
+
+void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) {
+ auto* const display = this->FindDisplay(display_id);
+ auto layer = this->FindLayer(consumer_binder_id);
+
+ if (!display || !layer) {
+ return;
+ }
+
+ display->stack.layers.emplace_back(std::move(layer));
+}
+
+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 (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
+ layer->visible = visible;
+ return;
+ }
+}
+
+void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) {
+ if (const 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;
+}
+
+std::shared_ptr<Layer> SurfaceFlinger::FindLayer(s32 consumer_binder_id) {
+ for (auto& layer : m_layers.layers) {
+ if (layer->consumer_id == consumer_binder_id) {
+ 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..406281c83
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/surface_flinger.h
@@ -0,0 +1,69 @@
+// 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 CreateLayer(s32 consumer_binder_id);
+ void DestroyLayer(s32 consumer_binder_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);
+ std::shared_ptr<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;
+ LayerStack m_layers;
+ std::shared_ptr<Nvidia::Module> nvdrv;
+ s32 disp_fd;
+ HardwareComposer m_composer;
+};
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/omm/omm.cpp b/src/core/hle/service/omm/omm.cpp
new file mode 100644
index 000000000..b95319e26
--- /dev/null
+++ b/src/core/hle/service/omm/omm.cpp
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/omm/omm.h"
+#include "core/hle/service/omm/operation_mode_manager.h"
+#include "core/hle/service/omm/policy_manager_system.h"
+#include "core/hle/service/omm/power_state_interface.h"
+#include "core/hle/service/server_manager.h"
+
+namespace Service::OMM {
+
+void LoopProcess(Core::System& system) {
+ auto server_manager = std::make_unique<ServerManager>(system);
+
+ server_manager->RegisterNamedService("idle:sys",
+ std::make_shared<IPolicyManagerSystem>(system));
+ server_manager->RegisterNamedService("omm", std::make_shared<IOperationModeManager>(system));
+ server_manager->RegisterNamedService("spsm", std::make_shared<IPowerStateInterface>(system));
+ ServerManager::RunServer(std::move(server_manager));
+}
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/omm.h b/src/core/hle/service/omm/omm.h
new file mode 100644
index 000000000..7bf04688a
--- /dev/null
+++ b/src/core/hle/service/omm/omm.h
@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+namespace Core {
+class System;
+}
+
+namespace Service::OMM {
+
+void LoopProcess(Core::System& system);
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/operation_mode_manager.cpp b/src/core/hle/service/omm/operation_mode_manager.cpp
new file mode 100644
index 000000000..fe7ed84a7
--- /dev/null
+++ b/src/core/hle/service/omm/operation_mode_manager.cpp
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/omm/operation_mode_manager.h"
+
+namespace Service::OMM {
+
+IOperationModeManager::IOperationModeManager(Core::System& system_)
+ : ServiceFramework{system_, "omm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetOperationMode"},
+ {1, nullptr, "GetOperationModeChangeEvent"},
+ {2, nullptr, "EnableAudioVisual"},
+ {3, nullptr, "DisableAudioVisual"},
+ {4, nullptr, "EnterSleepAndWait"},
+ {5, nullptr, "GetCradleStatus"},
+ {6, nullptr, "FadeInDisplay"},
+ {7, nullptr, "FadeOutDisplay"},
+ {8, nullptr, "GetCradleFwVersion"},
+ {9, nullptr, "NotifyCecSettingsChanged"},
+ {10, nullptr, "SetOperationModePolicy"},
+ {11, nullptr, "GetDefaultDisplayResolution"},
+ {12, nullptr, "GetDefaultDisplayResolutionChangeEvent"},
+ {13, nullptr, "UpdateDefaultDisplayResolution"},
+ {14, nullptr, "ShouldSleepOnBoot"},
+ {15, nullptr, "NotifyHdcpApplicationExecutionStarted"},
+ {16, nullptr, "NotifyHdcpApplicationExecutionFinished"},
+ {17, nullptr, "NotifyHdcpApplicationDrawingStarted"},
+ {18, nullptr, "NotifyHdcpApplicationDrawingFinished"},
+ {19, nullptr, "GetHdcpAuthenticationFailedEvent"},
+ {20, nullptr, "GetHdcpAuthenticationFailedEmulationEnabled"},
+ {21, nullptr, "SetHdcpAuthenticationFailedEmulation"},
+ {22, nullptr, "GetHdcpStateChangeEvent"},
+ {23, nullptr, "GetHdcpState"},
+ {24, nullptr, "ShowCardUpdateProcessing"},
+ {25, nullptr, "SetApplicationCecSettingsAndNotifyChanged"},
+ {26, nullptr, "GetOperationModeSystemInfo"},
+ {27, nullptr, "GetAppletFullAwakingSystemEvent"},
+ {28, nullptr, "CreateCradleFirmwareUpdater"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IOperationModeManager::~IOperationModeManager() = default;
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/operation_mode_manager.h b/src/core/hle/service/omm/operation_mode_manager.h
new file mode 100644
index 000000000..32bc7b2f9
--- /dev/null
+++ b/src/core/hle/service/omm/operation_mode_manager.h
@@ -0,0 +1,20 @@
+// 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::OMM {
+
+class IOperationModeManager final : public ServiceFramework<IOperationModeManager> {
+public:
+ explicit IOperationModeManager(Core::System& system_);
+ ~IOperationModeManager() override;
+};
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/policy_manager_system.cpp b/src/core/hle/service/omm/policy_manager_system.cpp
new file mode 100644
index 000000000..1cd6fd807
--- /dev/null
+++ b/src/core/hle/service/omm/policy_manager_system.cpp
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/omm/policy_manager_system.h"
+
+namespace Service::OMM {
+
+IPolicyManagerSystem::IPolicyManagerSystem(Core::System& system_)
+ : ServiceFramework{system_, "idle:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetAutoPowerDownEvent"},
+ {1, nullptr, "IsAutoPowerDownRequested"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "SetHandlingContext"},
+ {4, nullptr, "LoadAndApplySettings"},
+ {5, nullptr, "ReportUserIsActive"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IPolicyManagerSystem::~IPolicyManagerSystem() = default;
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/policy_manager_system.h b/src/core/hle/service/omm/policy_manager_system.h
new file mode 100644
index 000000000..151ca0d2e
--- /dev/null
+++ b/src/core/hle/service/omm/policy_manager_system.h
@@ -0,0 +1,20 @@
+// 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::OMM {
+
+class IPolicyManagerSystem final : public ServiceFramework<IPolicyManagerSystem> {
+public:
+ explicit IPolicyManagerSystem(Core::System& system_);
+ ~IPolicyManagerSystem() override;
+};
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/power_state_interface.cpp b/src/core/hle/service/omm/power_state_interface.cpp
new file mode 100644
index 000000000..22cac8259
--- /dev/null
+++ b/src/core/hle/service/omm/power_state_interface.cpp
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/omm/power_state_interface.h"
+
+namespace Service::OMM {
+
+IPowerStateInterface::IPowerStateInterface(Core::System& system_)
+ : ServiceFramework{system_, "spsm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "EnterSleep"},
+ {2, nullptr, "GetLastWakeReason"},
+ {3, nullptr, "Shutdown"},
+ {4, nullptr, "GetNotificationMessageEventHandle"},
+ {5, nullptr, "ReceiveNotificationMessage"},
+ {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"},
+ {7, nullptr, "ResetEventLog"},
+ {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"},
+ {9, nullptr, "ChangeHomeButtonLongPressingTime"},
+ {10, nullptr, "PutErrorState"},
+ {11, nullptr, "InvalidateCurrentHomeButtonPressing"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IPowerStateInterface::~IPowerStateInterface() = default;
+
+} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/power_state_interface.h b/src/core/hle/service/omm/power_state_interface.h
new file mode 100644
index 000000000..825a6512d
--- /dev/null
+++ b/src/core/hle/service/omm/power_state_interface.h
@@ -0,0 +1,20 @@
+// 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::OMM {
+
+class IPowerStateInterface final : public ServiceFramework<IPowerStateInterface> {
+public:
+ explicit IPowerStateInterface(Core::System& system_);
+ ~IPowerStateInterface() override;
+};
+
+} // namespace Service::OMM
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 f68c3c686..ce5e3b5b4 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -7,67 +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/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 {
@@ -208,81 +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("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/set/key_code_map.h b/src/core/hle/service/set/key_code_map.h
new file mode 100644
index 000000000..c76dc5729
--- /dev/null
+++ b/src/core/hle/service/set/key_code_map.h
@@ -0,0 +1,973 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <array>
+
+#include "common/common_types.h"
+
+namespace Service::Set {
+
+// Raw key codes map extracted from the settings sysmodule FW 16.2.0
+// This is nn::kpr::KeyCodeMap
+using KeyCodeMap = std::array<u8, 0x1000>;
+
+constexpr KeyCodeMap KeyCodeMapChineseTraditional = {
+ 0x61, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x07, 0x31, 0x00, 0x00, 0xE5, 0x65, 0x00, 0x00, 0x01, 0x10,
+ 0x62, 0x00, 0x42, 0x00, 0x16, 0x31, 0x00, 0x00, 0x08, 0x67, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00,
+ 0x43, 0x00, 0x0F, 0x31, 0x00, 0x00, 0xD1, 0x91, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00,
+ 0x0E, 0x31, 0x00, 0x00, 0x28, 0x67, 0x00, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x0D, 0x31,
+ 0x00, 0x00, 0x34, 0x6C, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x11, 0x31, 0x00, 0x00,
+ 0x6B, 0x70, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x15, 0x31, 0x00, 0x00, 0x1F, 0x57,
+ 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x18, 0x31, 0x00, 0x00, 0xF9, 0x7A, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x1B, 0x31, 0x00, 0x00, 0x08, 0x62, 0x00, 0x00, 0x01, 0x10,
+ 0x6A, 0x00, 0x4A, 0x00, 0x28, 0x31, 0x00, 0x00, 0x41, 0x53, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00,
+ 0x4B, 0x00, 0x1C, 0x31, 0x00, 0x00, 0x27, 0x59, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00,
+ 0x20, 0x31, 0x00, 0x00, 0x2D, 0x4E, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x29, 0x31,
+ 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x19, 0x31, 0x00, 0x00,
+ 0x13, 0x5F, 0x00, 0x00, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x1F, 0x31, 0x00, 0x00, 0xBA, 0x4E,
+ 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x23, 0x31, 0x00, 0x00, 0xC3, 0x5F, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x06, 0x31, 0x00, 0x00, 0x4B, 0x62, 0x00, 0x00, 0x01, 0x10,
+ 0x72, 0x00, 0x52, 0x00, 0x10, 0x31, 0x00, 0x00, 0xE3, 0x53, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00,
+ 0x53, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x38, 0x5C, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00,
+ 0x14, 0x31, 0x00, 0x00, 0xFF, 0x5E, 0x00, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x27, 0x31,
+ 0x00, 0x00, 0x71, 0x5C, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x12, 0x31, 0x00, 0x00,
+ 0x73, 0x59, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x0A, 0x31, 0x00, 0x00, 0x30, 0x75,
+ 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x0C, 0x31, 0x00, 0x00, 0xE3, 0x96, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x17, 0x31, 0x00, 0x00, 0x5C, 0x53, 0x00, 0x00, 0x01, 0x10,
+ 0x7A, 0x00, 0x5A, 0x00, 0x08, 0x31, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00,
+ 0x21, 0x00, 0x05, 0x31, 0x00, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10, 0x32, 0x00, 0x40, 0x00,
+ 0x09, 0x31, 0x00, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xC7, 0x02,
+ 0x00, 0x00, 0x33, 0x00, 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xCB, 0x02, 0x00, 0x00,
+ 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x13, 0x31, 0x00, 0x00, 0x35, 0x00,
+ 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0xCA, 0x02, 0x00, 0x00, 0x36, 0x00, 0x5E, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xD9, 0x02, 0x00, 0x00, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10,
+ 0x38, 0x00, 0x2A, 0x00, 0x1A, 0x31, 0x00, 0x00, 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00,
+ 0x28, 0x00, 0x1E, 0x31, 0x00, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00,
+ 0x22, 0x31, 0x00, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x2D, 0x00, 0x5F, 0x00, 0x26, 0x31, 0x00, 0x00, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00,
+ 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00,
+ 0x5B, 0x00, 0x7B, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x5D, 0x00,
+ 0x7D, 0x00, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00,
+ 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00,
+ 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x24, 0x31, 0x00, 0x00, 0x3B, 0x00, 0x3A, 0x00,
+ 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10,
+ 0x60, 0x00, 0x7E, 0x00, 0x60, 0x00, 0x7E, 0x00, 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00,
+ 0x3C, 0x00, 0x1D, 0x31, 0x00, 0x00, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00,
+ 0x21, 0x31, 0x00, 0x00, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x25, 0x31,
+ 0x00, 0x00, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10,
+ 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00,
+ 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20,
+ 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapChineseSimplified = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x01, 0x10, 0x63, 0x00,
+ 0x43, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x01, 0x10,
+ 0x66, 0x00, 0x46, 0x00, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x01, 0x10, 0x6B, 0x00,
+ 0x4B, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x01, 0x10,
+ 0x6E, 0x00, 0x4E, 0x00, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x01, 0x10, 0x73, 0x00,
+ 0x53, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x01, 0x10,
+ 0x76, 0x00, 0x56, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x10, 0x31, 0x00,
+ 0x21, 0x00, 0x00, 0x10, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x00, 0x10,
+ 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00,
+ 0x28, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00,
+ 0x2B, 0x00, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x10,
+ 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00,
+ 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10, 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00,
+ 0x3C, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00,
+ 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapKorean = {
+ 0x11, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x41, 0x31, 0x41, 0x31, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00,
+ 0x60, 0x31, 0x60, 0x31, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x4A, 0x31, 0x4A, 0x31, 0x01, 0x10,
+ 0x64, 0x00, 0x44, 0x00, 0x47, 0x31, 0x47, 0x31, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x37, 0x31,
+ 0x38, 0x31, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x39, 0x31, 0x39, 0x31, 0x01, 0x10, 0x67, 0x00,
+ 0x47, 0x00, 0x4E, 0x31, 0x4E, 0x31, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x57, 0x31, 0x57, 0x31,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x51, 0x31, 0x51, 0x31, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00,
+ 0x53, 0x31, 0x53, 0x31, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x4F, 0x31, 0x4F, 0x31, 0x01, 0x10,
+ 0x6C, 0x00, 0x4C, 0x00, 0x63, 0x31, 0x63, 0x31, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x61, 0x31,
+ 0x61, 0x31, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x5C, 0x31, 0x5C, 0x31, 0x01, 0x10, 0x6F, 0x00,
+ 0x4F, 0x00, 0x50, 0x31, 0x52, 0x31, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x54, 0x31, 0x56, 0x31,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x42, 0x31, 0x43, 0x31, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00,
+ 0x31, 0x31, 0x32, 0x31, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x34, 0x31, 0x34, 0x31, 0x01, 0x10,
+ 0x74, 0x00, 0x54, 0x00, 0x45, 0x31, 0x46, 0x31, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x55, 0x31,
+ 0x55, 0x31, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x4D, 0x31, 0x4D, 0x31, 0x01, 0x10, 0x77, 0x00,
+ 0x57, 0x00, 0x48, 0x31, 0x49, 0x31, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x4C, 0x31, 0x4C, 0x31,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x5B, 0x31, 0x5B, 0x31, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00,
+ 0x4B, 0x31, 0x4B, 0x31, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10,
+ 0x32, 0x00, 0x40, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x33, 0x00,
+ 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00,
+ 0x25, 0x00, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x36, 0x00, 0x5E, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00,
+ 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10,
+ 0x30, 0x00, 0x29, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00,
+ 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x10,
+ 0x5B, 0x00, 0x7B, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x5D, 0x00,
+ 0x7D, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00,
+ 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3A, 0x00,
+ 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10, 0x60, 0x00, 0x7E, 0x00,
+ 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x10,
+ 0x2E, 0x00, 0x3E, 0x00, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x2F, 0x00,
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00,
+ 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00,
+ 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapRussian = {
+ 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x10, 0x61, 0x00, 0x41, 0x00, 0x44, 0x04, 0x24, 0x04, 0x11, 0x10, 0x62, 0x00, 0x42, 0x00,
+ 0x38, 0x04, 0x18, 0x04, 0x11, 0x10, 0x63, 0x00, 0x43, 0x00, 0x41, 0x04, 0x21, 0x04, 0x11, 0x10,
+ 0x64, 0x00, 0x44, 0x00, 0x32, 0x04, 0x12, 0x04, 0x11, 0x10, 0x65, 0x00, 0x45, 0x00, 0x43, 0x04,
+ 0x23, 0x04, 0x11, 0x10, 0x66, 0x00, 0x46, 0x00, 0x30, 0x04, 0x10, 0x04, 0x11, 0x10, 0x67, 0x00,
+ 0x47, 0x00, 0x3F, 0x04, 0x1F, 0x04, 0x11, 0x10, 0x68, 0x00, 0x48, 0x00, 0x40, 0x04, 0x20, 0x04,
+ 0x11, 0x10, 0x69, 0x00, 0x49, 0x00, 0x48, 0x04, 0x28, 0x04, 0x11, 0x10, 0x6A, 0x00, 0x4A, 0x00,
+ 0x3E, 0x04, 0x1E, 0x04, 0x11, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x3B, 0x04, 0x1B, 0x04, 0x11, 0x10,
+ 0x6C, 0x00, 0x4C, 0x00, 0x34, 0x04, 0x14, 0x04, 0x11, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x4C, 0x04,
+ 0x2C, 0x04, 0x11, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x42, 0x04, 0x22, 0x04, 0x11, 0x10, 0x6F, 0x00,
+ 0x4F, 0x00, 0x49, 0x04, 0x29, 0x04, 0x11, 0x10, 0x70, 0x00, 0x50, 0x00, 0x37, 0x04, 0x17, 0x04,
+ 0x11, 0x10, 0x71, 0x00, 0x51, 0x00, 0x39, 0x04, 0x19, 0x04, 0x11, 0x10, 0x72, 0x00, 0x52, 0x00,
+ 0x3A, 0x04, 0x1A, 0x04, 0x11, 0x10, 0x73, 0x00, 0x53, 0x00, 0x4B, 0x04, 0x2B, 0x04, 0x11, 0x10,
+ 0x74, 0x00, 0x54, 0x00, 0x35, 0x04, 0x15, 0x04, 0x11, 0x10, 0x75, 0x00, 0x55, 0x00, 0x33, 0x04,
+ 0x13, 0x04, 0x11, 0x10, 0x76, 0x00, 0x56, 0x00, 0x3C, 0x04, 0x1C, 0x04, 0x11, 0x10, 0x77, 0x00,
+ 0x57, 0x00, 0x46, 0x04, 0x26, 0x04, 0x11, 0x10, 0x78, 0x00, 0x58, 0x00, 0x47, 0x04, 0x27, 0x04,
+ 0x11, 0x10, 0x79, 0x00, 0x59, 0x00, 0x3D, 0x04, 0x1D, 0x04, 0x11, 0x10, 0x7A, 0x00, 0x5A, 0x00,
+ 0x4F, 0x04, 0x2F, 0x04, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10,
+ 0x32, 0x00, 0x40, 0x00, 0x32, 0x00, 0x22, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x33, 0x00,
+ 0x16, 0x21, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x34, 0x00, 0x3B, 0x00, 0x00, 0x10, 0x35, 0x00,
+ 0x25, 0x00, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x36, 0x00, 0x3A, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x37, 0x00, 0x3F, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00,
+ 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10,
+ 0x30, 0x00, 0x29, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00,
+ 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x10, 0x10,
+ 0x5B, 0x00, 0x7B, 0x00, 0x45, 0x04, 0x25, 0x04, 0x10, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x4A, 0x04,
+ 0x2A, 0x04, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x5C, 0x00,
+ 0x7C, 0x00, 0x5C, 0x00, 0x2F, 0x00, 0x10, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x36, 0x04, 0x16, 0x04,
+ 0x10, 0x10, 0x27, 0x00, 0x22, 0x00, 0x4D, 0x04, 0x2D, 0x04, 0x10, 0x10, 0x60, 0x00, 0x7E, 0x00,
+ 0x51, 0x04, 0x01, 0x04, 0x10, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x31, 0x04, 0x11, 0x04, 0x10, 0x10,
+ 0x2E, 0x00, 0x3E, 0x00, 0x4E, 0x04, 0x2E, 0x04, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x2E, 0x00,
+ 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00,
+ 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00,
+ 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x00,
+ 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapPortuguese = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00,
+ 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA7, 0x00,
+ 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x5B, 0x00,
+ 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x5D, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x7D, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xAB, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x08, 0x03,
+ 0x00, 0x10, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x03, 0x03, 0x02, 0x03, 0x00, 0x00,
+ 0x00, 0x10, 0x03, 0x03, 0x02, 0x03, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xBA, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapItalian = {
+ 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20,
+ 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6F, 0x00,
+ 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00,
+ 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0xA3, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x35, 0x00,
+ 0x25, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xEC, 0x00, 0x5E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0xE8, 0x00, 0xE9, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x5D, 0x00,
+ 0x7D, 0x00, 0x00, 0x10, 0xF9, 0x00, 0xA7, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF9, 0x00,
+ 0xA7, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF2, 0x00, 0xE7, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xE0, 0x00, 0xB0, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00,
+ 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00,
+ 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapGerman = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x40, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x10, 0x32, 0x00, 0x22, 0x00, 0xB2, 0x00,
+ 0x01, 0x10, 0x33, 0x00, 0xA7, 0x00, 0xB3, 0x00, 0x01, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x7B, 0x00, 0x01, 0x10, 0x38, 0x00, 0x28, 0x00, 0x5B, 0x00,
+ 0x01, 0x10, 0x39, 0x00, 0x29, 0x00, 0x5D, 0x00, 0x01, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x7D, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x01, 0x10, 0xDF, 0x00, 0x3F, 0x00, 0x5C, 0x00,
+ 0x00, 0x10, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x01, 0x10, 0xFC, 0x00, 0xDC, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x7E, 0x00, 0x01, 0x10, 0x23, 0x00, 0x27, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x23, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, 0x10, 0xF6, 0x00, 0xD6, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0xE4, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x03, 0xB0, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapSpanishLatin = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x40, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x5C, 0x00,
+ 0x00, 0x10, 0xBF, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x03, 0x08, 0x03, 0x00, 0x00,
+ 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x7D, 0x00, 0x5D, 0x00, 0x00, 0x03,
+ 0x00, 0x10, 0x7D, 0x00, 0x5D, 0x00, 0x00, 0x03, 0x01, 0x10, 0xF1, 0x00, 0xD1, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x7B, 0x00, 0x5B, 0x00, 0x02, 0x03, 0x00, 0x10, 0x7C, 0x00, 0xB0, 0x00, 0xAC, 0x00,
+ 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapSpanish = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00,
+ 0x00, 0x10, 0x33, 0x00, 0xB7, 0x00, 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x03, 0x03,
+ 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0xAC, 0x20, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0xAC, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xA1, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x02, 0x03, 0x5B, 0x00,
+ 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x5D, 0x00, 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x7D, 0x00,
+ 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x7D, 0x00, 0x01, 0x10, 0xF1, 0x00, 0xD1, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x01, 0x03, 0x08, 0x03, 0x7B, 0x00, 0x00, 0x10, 0xBA, 0x00, 0xAA, 0x00, 0x5C, 0x00,
+ 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapFrenchCa = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0xA7, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0xB6, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0xB1, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00,
+ 0x00, 0x10, 0x33, 0x00, 0x2F, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA2, 0x00,
+ 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0xA4, 0x00, 0x00, 0x10, 0x36, 0x00, 0x3F, 0x00, 0xAC, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, 0xB2, 0x00,
+ 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0xB3, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00, 0xBC, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0xBD, 0x00,
+ 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0xBE, 0x00, 0x00, 0x10, 0x02, 0x03, 0x02, 0x03, 0x5B, 0x00,
+ 0x00, 0x10, 0x27, 0x03, 0x08, 0x03, 0x5D, 0x00, 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7D, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7D, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x7E, 0x00,
+ 0x00, 0x10, 0x00, 0x03, 0x00, 0x03, 0x7B, 0x00, 0x00, 0x10, 0x23, 0x00, 0x7C, 0x00, 0x5C, 0x00,
+ 0x00, 0x10, 0x2C, 0x00, 0x27, 0x00, 0xAF, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x2E, 0x00, 0x2D, 0x00,
+ 0x01, 0x10, 0xE9, 0x00, 0xC9, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xAB, 0x00, 0xBB, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapFrench = {
+ 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x2C, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x26, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x32, 0x00, 0x03, 0x03,
+ 0x01, 0x10, 0x22, 0x00, 0x33, 0x00, 0x23, 0x00, 0x01, 0x10, 0x27, 0x00, 0x34, 0x00, 0x7B, 0x00,
+ 0x01, 0x10, 0x28, 0x00, 0x35, 0x00, 0x5B, 0x00, 0x01, 0x10, 0x2D, 0x00, 0x36, 0x00, 0x7C, 0x00,
+ 0x01, 0x10, 0xE8, 0x00, 0x37, 0x00, 0x00, 0x03, 0x01, 0x10, 0x5F, 0x00, 0x38, 0x00, 0x5C, 0x00,
+ 0x01, 0x10, 0xE7, 0x00, 0x39, 0x00, 0x5E, 0x00, 0x01, 0x10, 0xE0, 0x00, 0x30, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x01, 0x10, 0x29, 0x00, 0xB0, 0x00, 0x5D, 0x00,
+ 0x01, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x7D, 0x00, 0x01, 0x10, 0x02, 0x03, 0x08, 0x03, 0x00, 0x00,
+ 0x01, 0x10, 0x24, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0x01, 0x10, 0x2A, 0x00, 0xB5, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x2A, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0xF9, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x3B, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x01, 0x10, 0x3A, 0x00, 0x2F, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x21, 0x00, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00,
+ 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapEnglishUk = {
+ 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x10, 0x61, 0x00, 0x41, 0x00, 0xE1, 0x00, 0xC1, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x65, 0x00, 0x45, 0x00, 0xE9, 0x00,
+ 0xC9, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x10, 0x69, 0x00, 0x49, 0x00, 0xED, 0x00, 0xCD, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x6F, 0x00,
+ 0x4F, 0x00, 0xF3, 0x00, 0xD3, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x75, 0x00, 0x55, 0x00, 0xFA, 0x00,
+ 0xDA, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00,
+ 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x32, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0xA3, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x35, 0x00,
+ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x23, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x23, 0x00,
+ 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x27, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x60, 0x00, 0xAC, 0x00,
+ 0xA6, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00,
+ 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00,
+ 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapJapanese = {
+ 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x61, 0x30, 0x61, 0x30, 0xC1, 0x30, 0xC1, 0x30, 0x01, 0x10,
+ 0x62, 0x00, 0x42, 0x00, 0x53, 0x30, 0x53, 0x30, 0xB3, 0x30, 0xB3, 0x30, 0x01, 0x10, 0x63, 0x00,
+ 0x43, 0x00, 0x5D, 0x30, 0x5D, 0x30, 0xBD, 0x30, 0xBD, 0x30, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00,
+ 0x57, 0x30, 0x57, 0x30, 0xB7, 0x30, 0xB7, 0x30, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x44, 0x30,
+ 0x43, 0x30, 0xA4, 0x30, 0xA3, 0x30, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x6F, 0x30, 0x6F, 0x30,
+ 0xCF, 0x30, 0xCF, 0x30, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x4D, 0x30, 0x4D, 0x30, 0xAD, 0x30,
+ 0xAD, 0x30, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x4F, 0x30, 0x4F, 0x30, 0xAF, 0x30, 0xAF, 0x30,
+ 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x6B, 0x30, 0x6B, 0x30, 0xCB, 0x30, 0xCB, 0x30, 0x01, 0x10,
+ 0x6A, 0x00, 0x4A, 0x00, 0x7E, 0x30, 0x7E, 0x30, 0xDE, 0x30, 0xDE, 0x30, 0x01, 0x10, 0x6B, 0x00,
+ 0x4B, 0x00, 0x6E, 0x30, 0x6E, 0x30, 0xCE, 0x30, 0xCE, 0x30, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00,
+ 0x8A, 0x30, 0x8A, 0x30, 0xEA, 0x30, 0xEA, 0x30, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x82, 0x30,
+ 0x82, 0x30, 0xE2, 0x30, 0xE2, 0x30, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x7F, 0x30, 0x7F, 0x30,
+ 0xDF, 0x30, 0xDF, 0x30, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x89, 0x30, 0x89, 0x30, 0xE9, 0x30,
+ 0xE9, 0x30, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x5B, 0x30, 0x5B, 0x30, 0xBB, 0x30, 0xBB, 0x30,
+ 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x5F, 0x30, 0x5F, 0x30, 0xBF, 0x30, 0xBF, 0x30, 0x01, 0x10,
+ 0x72, 0x00, 0x52, 0x00, 0x59, 0x30, 0x59, 0x30, 0xB9, 0x30, 0xB9, 0x30, 0x01, 0x10, 0x73, 0x00,
+ 0x53, 0x00, 0x68, 0x30, 0x68, 0x30, 0xC8, 0x30, 0xC8, 0x30, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00,
+ 0x4B, 0x30, 0x4B, 0x30, 0xAB, 0x30, 0xAB, 0x30, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x6A, 0x30,
+ 0x6A, 0x30, 0xCA, 0x30, 0xCA, 0x30, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x72, 0x30, 0x72, 0x30,
+ 0xD2, 0x30, 0xD2, 0x30, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x66, 0x30, 0x66, 0x30, 0xC6, 0x30,
+ 0xC6, 0x30, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x55, 0x30, 0x55, 0x30, 0xB5, 0x30, 0xB5, 0x30,
+ 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x93, 0x30, 0x93, 0x30, 0xF3, 0x30, 0xF3, 0x30, 0x01, 0x10,
+ 0x7A, 0x00, 0x5A, 0x00, 0x64, 0x30, 0x63, 0x30, 0xC4, 0x30, 0xC3, 0x30, 0x00, 0x10, 0x31, 0x00,
+ 0x21, 0x00, 0x6C, 0x30, 0x6C, 0x30, 0xCC, 0x30, 0xCC, 0x30, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00,
+ 0x75, 0x30, 0x75, 0x30, 0xD5, 0x30, 0xD5, 0x30, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x42, 0x30,
+ 0x41, 0x30, 0xA2, 0x30, 0xA1, 0x30, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x46, 0x30, 0x45, 0x30,
+ 0xA6, 0x30, 0xA5, 0x30, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x48, 0x30, 0x47, 0x30, 0xA8, 0x30,
+ 0xA7, 0x30, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x4A, 0x30, 0x49, 0x30, 0xAA, 0x30, 0xA9, 0x30,
+ 0x00, 0x10, 0x37, 0x00, 0x27, 0x00, 0x84, 0x30, 0x83, 0x30, 0xE4, 0x30, 0xE3, 0x30, 0x00, 0x10,
+ 0x38, 0x00, 0x28, 0x00, 0x86, 0x30, 0x85, 0x30, 0xE6, 0x30, 0xE5, 0x30, 0x00, 0x10, 0x39, 0x00,
+ 0x29, 0x00, 0x88, 0x30, 0x87, 0x30, 0xE8, 0x30, 0xE7, 0x30, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00,
+ 0x8F, 0x30, 0x92, 0x30, 0xEF, 0x30, 0xF2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10,
+ 0x2D, 0x00, 0x3D, 0x00, 0x7B, 0x30, 0x7B, 0x30, 0xDB, 0x30, 0xDB, 0x30, 0x00, 0x10, 0x5E, 0x00,
+ 0x7E, 0x00, 0x78, 0x30, 0x78, 0x30, 0xD8, 0x30, 0xD8, 0x30, 0x00, 0x10, 0x40, 0x00, 0x60, 0x00,
+ 0x9E, 0xFF, 0x9E, 0xFF, 0x9E, 0xFF, 0x9E, 0xFF, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00, 0x9F, 0xFF,
+ 0x62, 0xFF, 0x9F, 0xFF, 0x62, 0xFF, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x80, 0x30, 0x63, 0xFF,
+ 0xE0, 0x30, 0x63, 0xFF, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x80, 0x30, 0x63, 0xFF, 0xE0, 0x30,
+ 0x63, 0xFF, 0x00, 0x10, 0x3B, 0x00, 0x2B, 0x00, 0x8C, 0x30, 0x8C, 0x30, 0xEC, 0x30, 0xEC, 0x30,
+ 0x00, 0x10, 0x3A, 0x00, 0x2A, 0x00, 0x51, 0x30, 0x51, 0x30, 0xB1, 0x30, 0xB1, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00,
+ 0x3C, 0x00, 0x6D, 0x30, 0x64, 0xFF, 0xCD, 0x30, 0x64, 0xFF, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00,
+ 0x8B, 0x30, 0x61, 0xFF, 0xEB, 0x30, 0x61, 0xFF, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x81, 0x30,
+ 0x65, 0xFF, 0xE1, 0x30, 0x65, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10,
+ 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00,
+ 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00,
+ 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20,
+ 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00,
+ 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x5F, 0x00,
+ 0x8D, 0x30, 0x8D, 0x30, 0xED, 0x30, 0xED, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x70, 0xFF, 0x70, 0xFF,
+ 0x70, 0xFF, 0x70, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+constexpr KeyCodeMap KeyCodeMapEnglishUsInternational = {
+ 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x10, 0x61, 0x00, 0x41, 0x00, 0xE1, 0x00, 0xC1, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0xA9, 0x00, 0xA2, 0x00, 0x03, 0x10,
+ 0x64, 0x00, 0x44, 0x00, 0xF0, 0x00, 0xD0, 0x00, 0x03, 0x10, 0x65, 0x00, 0x45, 0x00, 0xE9, 0x00,
+ 0xC9, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00,
+ 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x10, 0x69, 0x00, 0x49, 0x00, 0xED, 0x00, 0xCD, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10,
+ 0x6C, 0x00, 0x4C, 0x00, 0xF8, 0x00, 0xD8, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00,
+ 0x00, 0x00, 0x03, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0xF1, 0x00, 0xD1, 0x00, 0x03, 0x10, 0x6F, 0x00,
+ 0x4F, 0x00, 0xF3, 0x00, 0xD3, 0x00, 0x03, 0x10, 0x70, 0x00, 0x50, 0x00, 0xF6, 0x00, 0xD6, 0x00,
+ 0x03, 0x10, 0x71, 0x00, 0x51, 0x00, 0xE4, 0x00, 0xC4, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00,
+ 0xAE, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0xDF, 0x00, 0xA7, 0x00, 0x03, 0x10,
+ 0x74, 0x00, 0x54, 0x00, 0xFE, 0x00, 0xDE, 0x00, 0x03, 0x10, 0x75, 0x00, 0x55, 0x00, 0xFA, 0x00,
+ 0xDA, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x77, 0x00,
+ 0x57, 0x00, 0xE5, 0x00, 0xC5, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x10, 0x79, 0x00, 0x59, 0x00, 0xFC, 0x00, 0xDC, 0x00, 0x03, 0x10, 0x7A, 0x00, 0x5A, 0x00,
+ 0xE6, 0x00, 0xC6, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0xA1, 0x00, 0xB9, 0x00, 0x00, 0x10,
+ 0x32, 0x00, 0x40, 0x00, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xB3, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA4, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x35, 0x00,
+ 0x25, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x02, 0x03, 0xBC, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00,
+ 0xBE, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x18, 0x20, 0x00, 0x00, 0x00, 0x10,
+ 0x30, 0x00, 0x29, 0x00, 0x19, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00,
+ 0xA5, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0xD7, 0x00, 0xF7, 0x00, 0x00, 0x10,
+ 0x5B, 0x00, 0x7B, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0xBB, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0xAC, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x5C, 0x00,
+ 0x7C, 0x00, 0xAC, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0xB6, 0x00, 0xB0, 0x00,
+ 0x00, 0x10, 0x0D, 0x03, 0x0E, 0x03, 0xB4, 0x00, 0xA8, 0x00, 0x00, 0x10, 0x00, 0x03, 0x03, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0xE7, 0x00, 0xC7, 0x00, 0x00, 0x10,
+ 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0xBF, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00,
+ 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10,
+ 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00,
+ 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00,
+ 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20,
+ 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00,
+ 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+} // namespace Service::Set
diff --git a/src/core/hle/service/set/private_settings.h b/src/core/hle/service/set/private_settings.h
deleted file mode 100644
index b02291ce7..000000000
--- a/src/core/hle/service/set/private_settings.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <array>
-
-#include "common/bit_field.h"
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "common/uuid.h"
-#include "core/hle/service/psc/time/common.h"
-
-namespace Service::Set {
-
-/// This is nn::settings::system::InitialLaunchFlag
-struct InitialLaunchFlag {
- union {
- u32 raw{};
-
- BitField<0, 1, u32> InitialLaunchCompletionFlag;
- BitField<8, 1, u32> InitialLaunchUserAdditionFlag;
- BitField<16, 1, u32> InitialLaunchTimestampFlag;
- };
-};
-static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size");
-
-/// This is nn::settings::system::InitialLaunchSettings
-struct InitialLaunchSettings {
- InitialLaunchFlag flags;
- INSERT_PADDING_BYTES(0x4);
- Service::PSC::Time::SteadyClockTimePoint timestamp;
-};
-static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size");
-
-#pragma pack(push, 4)
-struct InitialLaunchSettingsPacked {
- InitialLaunchFlag flags;
- Service::PSC::Time::SteadyClockTimePoint timestamp;
-};
-#pragma pack(pop)
-static_assert(sizeof(InitialLaunchSettingsPacked) == 0x1C,
- "InitialLaunchSettingsPacked is incorrect size");
-
-struct PrivateSettings {
- std::array<u8, 0x10> reserved_00;
-
- // nn::settings::system::InitialLaunchSettings
- InitialLaunchSettings initial_launch_settings;
-
- std::array<u8, 0x20> reserved_30;
-
- Common::UUID external_clock_source_id;
- s64 shutdown_rtc_value;
- s64 external_steady_clock_internal_offset;
-
- std::array<u8, 0x60> reserved_70;
-
- // nn::settings::system::PlatformRegion
- std::array<u8, 0x4> platform_region;
-
- std::array<u8, 0x4> reserved_D4;
-};
-static_assert(offsetof(PrivateSettings, initial_launch_settings) == 0x10);
-static_assert(offsetof(PrivateSettings, external_clock_source_id) == 0x50);
-static_assert(offsetof(PrivateSettings, reserved_70) == 0x70);
-static_assert(offsetof(PrivateSettings, platform_region) == 0xD0);
-static_assert(sizeof(PrivateSettings) == 0xD8, "PrivateSettings has the wrong size!");
-
-PrivateSettings DefaultPrivateSettings();
-
-} // namespace Service::Set
diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h
index 40230182a..a5b1552a5 100644
--- a/src/core/hle/service/set/setting_formats/system_settings.h
+++ b/src/core/hle/service/set/setting_formats/system_settings.h
@@ -244,7 +244,7 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x60); // Reserved
// nn::settings::system::AccountNotificationSettings
- u32 account_notification_settings_count;
+ s32 account_notification_settings_count;
INSERT_PADDING_BYTES(0xC); // Reserved
std::array<AccountNotificationSettings, 8> account_notification_settings;
INSERT_PADDING_BYTES(0x140); // Reserved
@@ -308,7 +308,7 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x34); // Reserved
// nn::settings::system::EulaVersion
- u32 eula_version_count;
+ s32 eula_version_count;
INSERT_PADDING_BYTES(0xC); // Reserved
std::array<EulaVersion, 32> eula_versions;
INSERT_PADDING_BYTES(0x200); // Reserved
diff --git a/src/core/hle/service/set/settings_server.cpp b/src/core/hle/service/set/settings_server.cpp
index b2caa00ff..a9321b98d 100644
--- a/src/core/hle/service/set/settings_server.cpp
+++ b/src/core/hle/service/set/settings_server.cpp
@@ -6,7 +6,9 @@
#include <chrono>
#include "common/logging/log.h"
#include "common/settings.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/set/key_code_map.h"
#include "core/hle/service/set/settings_server.h"
namespace Service::Set {
@@ -15,43 +17,69 @@ constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
constexpr Result ResultInvalidLanguage{ErrorModule::Settings, 625};
-
-void PushResponseLanguageCode(HLERequestContext& ctx, std::size_t num_language_codes) {
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(num_language_codes));
-}
-
-void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entries) {
- const std::size_t requested_amount = ctx.GetWriteBufferNumElements<LanguageCode>();
- const std::size_t max_amount = std::min(requested_amount, max_entries);
- const std::size_t copy_amount = std::min(available_language_codes.size(), max_amount);
- const std::size_t copy_size = copy_amount * sizeof(LanguageCode);
-
- ctx.WriteBuffer(available_language_codes.data(), copy_size);
- PushResponseLanguageCode(ctx, copy_amount);
-}
-
-void GetKeyCodeMapImpl(HLERequestContext& ctx) {
- const auto language_code =
- available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
- const auto key_code =
- std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
- [=](const auto& element) { return element.first == language_code; });
- KeyboardLayout layout = KeyboardLayout::EnglishUs;
- if (key_code == language_to_layout.cend()) {
- LOG_ERROR(Service_SET,
- "Could not find keyboard layout for language index {}, defaulting to English us",
- Settings::values.language_index.GetValue());
- } else {
- layout = key_code->second;
+constexpr Result ResultNullPointer{ErrorModule::Settings, 1261};
+
+Result GetKeyCodeMapImpl(KeyCodeMap& out_key_code_map, KeyboardLayout keyboard_layout,
+ LanguageCode language_code) {
+ switch (keyboard_layout) {
+ case KeyboardLayout::Japanese:
+ out_key_code_map = KeyCodeMapJapanese;
+ R_SUCCEED();
+ case KeyboardLayout::EnglishUs:
+ out_key_code_map = KeyCodeMapEnglishUsInternational;
+ if (language_code == LanguageCode::KO) {
+ out_key_code_map = KeyCodeMapKorean;
+ }
+ if (language_code == LanguageCode::ZH_HANS) {
+ out_key_code_map = KeyCodeMapChineseSimplified;
+ }
+ if (language_code == LanguageCode::ZH_HANT) {
+ out_key_code_map = KeyCodeMapChineseTraditional;
+ }
+ R_SUCCEED();
+ case KeyboardLayout::EnglishUk:
+ out_key_code_map = KeyCodeMapEnglishUk;
+ R_SUCCEED();
+ case KeyboardLayout::French:
+ out_key_code_map = KeyCodeMapFrench;
+ R_SUCCEED();
+ case KeyboardLayout::FrenchCa:
+ out_key_code_map = KeyCodeMapFrenchCa;
+ R_SUCCEED();
+ case KeyboardLayout::Spanish:
+ out_key_code_map = KeyCodeMapSpanish;
+ R_SUCCEED();
+ case KeyboardLayout::SpanishLatin:
+ out_key_code_map = KeyCodeMapSpanishLatin;
+ R_SUCCEED();
+ case KeyboardLayout::German:
+ out_key_code_map = KeyCodeMapGerman;
+ R_SUCCEED();
+ case KeyboardLayout::Italian:
+ out_key_code_map = KeyCodeMapItalian;
+ R_SUCCEED();
+ case KeyboardLayout::Portuguese:
+ out_key_code_map = KeyCodeMapPortuguese;
+ R_SUCCEED();
+ case KeyboardLayout::Russian:
+ out_key_code_map = KeyCodeMapRussian;
+ R_SUCCEED();
+ case KeyboardLayout::Korean:
+ out_key_code_map = KeyCodeMapKorean;
+ R_SUCCEED();
+ case KeyboardLayout::ChineseSimplified:
+ out_key_code_map = KeyCodeMapChineseSimplified;
+ R_SUCCEED();
+ case KeyboardLayout::ChineseTraditional:
+ out_key_code_map = KeyCodeMapChineseTraditional;
+ R_SUCCEED();
+ default:
+ case KeyboardLayout::EnglishUsInternational:
+ out_key_code_map = KeyCodeMapEnglishUsInternational;
+ R_SUCCEED();
}
-
- ctx.WriteBuffer(layout);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
}
+
} // Anonymous namespace
LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
@@ -61,18 +89,18 @@ LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{system_, "set"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &ISettingsServer::GetLanguageCode, "GetLanguageCode"},
- {1, &ISettingsServer::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
- {2, &ISettingsServer::MakeLanguageCode, "MakeLanguageCode"},
- {3, &ISettingsServer::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
- {4, &ISettingsServer::GetRegionCode, "GetRegionCode"},
- {5, &ISettingsServer::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
- {6, &ISettingsServer::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
- {7, &ISettingsServer::GetKeyCodeMap, "GetKeyCodeMap"},
- {8, &ISettingsServer::GetQuestFlag, "GetQuestFlag"},
- {9, &ISettingsServer::GetKeyCodeMap2, "GetKeyCodeMap2"},
+ {0, C<&ISettingsServer::GetLanguageCode>, "GetLanguageCode"},
+ {1, C<&ISettingsServer::GetAvailableLanguageCodes>, "GetAvailableLanguageCodes"},
+ {2, C<&ISettingsServer::MakeLanguageCode>, "MakeLanguageCode"},
+ {3, C<&ISettingsServer::GetAvailableLanguageCodeCount>, "GetAvailableLanguageCodeCount"},
+ {4, C<&ISettingsServer::GetRegionCode>, "GetRegionCode"},
+ {5, C<&ISettingsServer::GetAvailableLanguageCodes2>, "GetAvailableLanguageCodes2"},
+ {6, C<&ISettingsServer::GetAvailableLanguageCodeCount2>, "GetAvailableLanguageCodeCount2"},
+ {7, C<&ISettingsServer::GetKeyCodeMap>, "GetKeyCodeMap"},
+ {8, C<&ISettingsServer::GetQuestFlag>, "GetQuestFlag"},
+ {9, C<&ISettingsServer::GetKeyCodeMap2>, "GetKeyCodeMap2"},
{10, nullptr, "GetFirmwareVersionForDebug"},
- {11, &ISettingsServer::GetDeviceNickName, "GetDeviceNickName"},
+ {11, C<&ISettingsServer::GetDeviceNickName>, "GetDeviceNickName"},
};
// clang-format on
@@ -81,86 +109,134 @@ ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{syste
ISettingsServer::~ISettingsServer() = default;
-void ISettingsServer::GetAvailableLanguageCodes(HLERequestContext& ctx) {
+Result ISettingsServer::GetLanguageCode(Out<LanguageCode> out_language_code) {
+ LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue());
+
+ *out_language_code = available_language_codes[static_cast<std::size_t>(
+ Settings::values.language_index.GetValue())];
+ R_SUCCEED();
+}
+
+Result ISettingsServer::GetAvailableLanguageCodes(
+ Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcPointer> out_language_codes) {
LOG_DEBUG(Service_SET, "called");
- GetAvailableLanguageCodesImpl(ctx, PRE_4_0_0_MAX_ENTRIES);
+ const std::size_t max_amount = std::min(PRE_4_0_0_MAX_ENTRIES, out_language_codes.size());
+ *out_count = static_cast<s32>(std::min(available_language_codes.size(), max_amount));
+
+ memcpy(out_language_codes.data(), available_language_codes.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(LanguageCode));
+
+ R_SUCCEED();
}
-void ISettingsServer::MakeLanguageCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto index = rp.Pop<u32>();
+Result ISettingsServer::MakeLanguageCode(Out<LanguageCode> out_language_code, Language language) {
+ LOG_DEBUG(Service_SET, "called, language={}", language);
- if (index >= available_language_codes.size()) {
- LOG_ERROR(Service_SET, "Invalid language code index! index={}", index);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(Set::ResultInvalidLanguage);
- return;
- }
+ const auto index = static_cast<std::size_t>(language);
+ R_UNLESS(index < available_language_codes.size(), Set::ResultInvalidLanguage);
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(available_language_codes[index]);
+ *out_language_code = available_language_codes[index];
+ R_SUCCEED();
}
-void ISettingsServer::GetAvailableLanguageCodes2(HLERequestContext& ctx) {
+Result ISettingsServer::GetAvailableLanguageCodeCount(Out<s32> out_count) {
LOG_DEBUG(Service_SET, "called");
- GetAvailableLanguageCodesImpl(ctx, POST_4_0_0_MAX_ENTRIES);
+ *out_count = PRE_4_0_0_MAX_ENTRIES;
+ R_SUCCEED();
}
-void ISettingsServer::GetAvailableLanguageCodeCount(HLERequestContext& ctx) {
+Result ISettingsServer::GetRegionCode(Out<SystemRegionCode> out_region_code) {
LOG_DEBUG(Service_SET, "called");
- PushResponseLanguageCode(ctx, PRE_4_0_0_MAX_ENTRIES);
+ *out_region_code = static_cast<SystemRegionCode>(Settings::values.region_index.GetValue());
+ R_SUCCEED();
}
-void ISettingsServer::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) {
+Result ISettingsServer::GetAvailableLanguageCodes2(
+ Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcMapAlias> language_codes) {
LOG_DEBUG(Service_SET, "called");
- PushResponseLanguageCode(ctx, POST_4_0_0_MAX_ENTRIES);
+ const std::size_t max_amount = std::min(POST_4_0_0_MAX_ENTRIES, language_codes.size());
+ *out_count = static_cast<s32>(std::min(available_language_codes.size(), max_amount));
+
+ memcpy(language_codes.data(), available_language_codes.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(LanguageCode));
+
+ R_SUCCEED();
}
-void ISettingsServer::GetQuestFlag(HLERequestContext& ctx) {
+Result ISettingsServer::GetAvailableLanguageCodeCount2(Out<s32> out_count) {
LOG_DEBUG(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue()));
+ *out_count = POST_4_0_0_MAX_ENTRIES;
+ R_SUCCEED();
}
-void ISettingsServer::GetLanguageCode(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue());
+Result ISettingsServer::GetKeyCodeMap(
+ OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map) {
+ LOG_DEBUG(Service_SET, "called");
+
+ R_UNLESS(out_key_code_map != nullptr, ResultNullPointer);
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(
- available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]);
+ const auto language_code =
+ available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
+ const auto key_code =
+ std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
+ [=](const auto& element) { return element.first == language_code; });
+
+ if (key_code == language_to_layout.cend()) {
+ LOG_ERROR(Service_SET,
+ "Could not find keyboard layout for language index {}, defaulting to English us",
+ Settings::values.language_index.GetValue());
+ *out_key_code_map = KeyCodeMapEnglishUsInternational;
+ R_SUCCEED();
+ }
+
+ R_RETURN(GetKeyCodeMapImpl(*out_key_code_map, key_code->second, key_code->first));
}
-void ISettingsServer::GetRegionCode(HLERequestContext& ctx) {
+Result ISettingsServer::GetQuestFlag(Out<bool> out_quest_flag) {
LOG_DEBUG(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(Settings::values.region_index.GetValue()));
+ *out_quest_flag = Settings::values.quest_flag.GetValue();
+ R_SUCCEED();
}
-void ISettingsServer::GetKeyCodeMap(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
- GetKeyCodeMapImpl(ctx);
-}
+Result ISettingsServer::GetKeyCodeMap2(
+ OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map) {
+ LOG_DEBUG(Service_SET, "called");
+
+ R_UNLESS(out_key_code_map != nullptr, ResultNullPointer);
-void ISettingsServer::GetKeyCodeMap2(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
- GetKeyCodeMapImpl(ctx);
+ const auto language_code =
+ available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())];
+ const auto key_code =
+ std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
+ [=](const auto& element) { return element.first == language_code; });
+
+ if (key_code == language_to_layout.cend()) {
+ LOG_ERROR(Service_SET,
+ "Could not find keyboard layout for language index {}, defaulting to English us",
+ Settings::values.language_index.GetValue());
+ *out_key_code_map = KeyCodeMapEnglishUsInternational;
+ R_SUCCEED();
+ }
+
+ R_RETURN(GetKeyCodeMapImpl(*out_key_code_map, key_code->second, key_code->first));
}
-void ISettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
+Result ISettingsServer::GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name) {
LOG_DEBUG(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- ctx.WriteBuffer(Settings::values.device_name.GetValue());
+
+ const std::size_t string_size =
+ std::min(Settings::values.device_name.GetValue().size(), out_device_name->size());
+
+ *out_device_name = {};
+ memcpy(out_device_name->data(), Settings::values.device_name.GetValue().data(), string_size);
+ R_SUCCEED();
}
} // namespace Service::Set
diff --git a/src/core/hle/service/set/settings_server.h b/src/core/hle/service/set/settings_server.h
index 8304e8424..a39971fe9 100644
--- a/src/core/hle/service/set/settings_server.h
+++ b/src/core/hle/service/set/settings_server.h
@@ -3,6 +3,7 @@
#pragma once
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings_types.h"
@@ -11,6 +12,7 @@ class System;
}
namespace Service::Set {
+using KeyCodeMap = std::array<u8, 0x1000>;
LanguageCode GetLanguageCodeFromIndex(std::size_t idx);
@@ -20,17 +22,30 @@ public:
~ISettingsServer() override;
private:
- void GetLanguageCode(HLERequestContext& ctx);
- void GetAvailableLanguageCodes(HLERequestContext& ctx);
- void MakeLanguageCode(HLERequestContext& ctx);
- void GetAvailableLanguageCodes2(HLERequestContext& ctx);
- void GetAvailableLanguageCodeCount(HLERequestContext& ctx);
- void GetAvailableLanguageCodeCount2(HLERequestContext& ctx);
- void GetQuestFlag(HLERequestContext& ctx);
- void GetRegionCode(HLERequestContext& ctx);
- void GetKeyCodeMap(HLERequestContext& ctx);
- void GetKeyCodeMap2(HLERequestContext& ctx);
- void GetDeviceNickName(HLERequestContext& ctx);
+ Result GetLanguageCode(Out<LanguageCode> out_language_code);
+
+ Result GetAvailableLanguageCodes(Out<s32> out_count,
+ OutArray<LanguageCode, BufferAttr_HipcPointer> language_codes);
+
+ Result MakeLanguageCode(Out<LanguageCode> out_language_code, Language language);
+
+ Result GetAvailableLanguageCodeCount(Out<s32> out_count);
+
+ Result GetRegionCode(Out<SystemRegionCode> out_region_code);
+
+ Result GetAvailableLanguageCodes2(
+ Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcMapAlias> language_codes);
+
+ Result GetAvailableLanguageCodeCount2(Out<s32> out_count);
+
+ Result GetKeyCodeMap(OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map);
+
+ Result GetQuestFlag(Out<bool> out_quest_flag);
+
+ Result GetKeyCodeMap2(OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map);
+
+ Result GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name);
};
} // namespace Service::Set
diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h
index ceb85b82a..29664e88c 100644
--- a/src/core/hle/service/set/settings_types.h
+++ b/src/core/hle/service/set/settings_types.h
@@ -12,6 +12,7 @@
#include "core/hle/service/psc/time/common.h"
namespace Service::Set {
+using SettingItemName = std::array<u8, 0x48>;
/// This is nn::settings::system::AudioOutputMode
enum class AudioOutputMode : u32 {
@@ -148,6 +149,28 @@ enum class KeyboardLayout : u32 {
ChineseTraditional = 14,
};
+// This is nn::settings::Language
+enum class Language : u32 {
+ Japanese,
+ AmericanEnglish,
+ French,
+ German,
+ Italian,
+ Spanish,
+ Chinese,
+ Korean,
+ Dutch,
+ Portiguesue,
+ Russian,
+ Taiwanese,
+ BritishEnglish,
+ CanadianFrench,
+ LatinAmericanSpanish,
+ SimplifiedCHhinese,
+ TraditionalChinese,
+ BrazilianPortuguese,
+};
+
/// This is "nn::settings::LanguageCode", which is a NUL-terminated string stored in a u64.
enum class LanguageCode : u64 {
JA = 0x000000000000616A,
@@ -391,16 +414,18 @@ struct FirmwareVersionFormat {
u8 major;
u8 minor;
u8 micro;
- INSERT_PADDING_BYTES(1);
+ INSERT_PADDING_BYTES_NOINIT(1);
u8 revision_major;
u8 revision_minor;
- INSERT_PADDING_BYTES(2);
+ INSERT_PADDING_BYTES_NOINIT(2);
std::array<char, 0x20> platform;
std::array<u8, 0x40> version_hash;
std::array<char, 0x18> display_version;
std::array<char, 0x80> display_title;
};
static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size");
+static_assert(std::is_trivial_v<FirmwareVersionFormat>,
+ "FirmwareVersionFormat type must be trivially copyable.");
/// This is nn::settings::system::HomeMenuScheme
struct HomeMenuScheme {
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp
index 7ef4a0ded..93925f783 100644
--- a/src/core/hle/service/set/system_settings_server.cpp
+++ b/src/core/hle/service/set/system_settings_server.cpp
@@ -17,6 +17,7 @@
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/system_archive.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/set/settings_server.h"
@@ -91,83 +92,83 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
: ServiceFramework{system_, "set:sys"}, m_system{system} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &ISystemSettingsServer::SetLanguageCode, "SetLanguageCode"},
+ {0, C<&ISystemSettingsServer::SetLanguageCode>, "SetLanguageCode"},
{1, nullptr, "SetNetworkSettings"},
{2, nullptr, "GetNetworkSettings"},
- {3, &ISystemSettingsServer::GetFirmwareVersion, "GetFirmwareVersion"},
- {4, &ISystemSettingsServer::GetFirmwareVersion2, "GetFirmwareVersion2"},
+ {3, C<&ISystemSettingsServer::GetFirmwareVersion>, "GetFirmwareVersion"},
+ {4, C<&ISystemSettingsServer::GetFirmwareVersion2>, "GetFirmwareVersion2"},
{5, nullptr, "GetFirmwareVersionDigest"},
- {7, &ISystemSettingsServer::GetLockScreenFlag, "GetLockScreenFlag"},
- {8, &ISystemSettingsServer::SetLockScreenFlag, "SetLockScreenFlag"},
+ {7, C<&ISystemSettingsServer::GetLockScreenFlag>, "GetLockScreenFlag"},
+ {8, C<&ISystemSettingsServer::SetLockScreenFlag>, "SetLockScreenFlag"},
{9, nullptr, "GetBacklightSettings"},
{10, nullptr, "SetBacklightSettings"},
{11, nullptr, "SetBluetoothDevicesSettings"},
{12, nullptr, "GetBluetoothDevicesSettings"},
- {13, &ISystemSettingsServer::GetExternalSteadyClockSourceId, "GetExternalSteadyClockSourceId"},
- {14, &ISystemSettingsServer::SetExternalSteadyClockSourceId, "SetExternalSteadyClockSourceId"},
- {15, &ISystemSettingsServer::GetUserSystemClockContext, "GetUserSystemClockContext"},
- {16, &ISystemSettingsServer::SetUserSystemClockContext, "SetUserSystemClockContext"},
- {17, &ISystemSettingsServer::GetAccountSettings, "GetAccountSettings"},
- {18, &ISystemSettingsServer::SetAccountSettings, "SetAccountSettings"},
+ {13, C<&ISystemSettingsServer::GetExternalSteadyClockSourceId>, "GetExternalSteadyClockSourceId"},
+ {14, C<&ISystemSettingsServer::SetExternalSteadyClockSourceId>, "SetExternalSteadyClockSourceId"},
+ {15, C<&ISystemSettingsServer::GetUserSystemClockContext>, "GetUserSystemClockContext"},
+ {16, C<&ISystemSettingsServer::SetUserSystemClockContext>, "SetUserSystemClockContext"},
+ {17, C<&ISystemSettingsServer::GetAccountSettings>, "GetAccountSettings"},
+ {18, C<&ISystemSettingsServer::SetAccountSettings>, "SetAccountSettings"},
{19, nullptr, "GetAudioVolume"},
{20, nullptr, "SetAudioVolume"},
- {21, &ISystemSettingsServer::GetEulaVersions, "GetEulaVersions"},
- {22, &ISystemSettingsServer::SetEulaVersions, "SetEulaVersions"},
- {23, &ISystemSettingsServer::GetColorSetId, "GetColorSetId"},
- {24, &ISystemSettingsServer::SetColorSetId, "SetColorSetId"},
+ {21, C<&ISystemSettingsServer::GetEulaVersions>, "GetEulaVersions"},
+ {22, C<&ISystemSettingsServer::SetEulaVersions>, "SetEulaVersions"},
+ {23, C<&ISystemSettingsServer::GetColorSetId>, "GetColorSetId"},
+ {24, C<&ISystemSettingsServer::SetColorSetId>, "SetColorSetId"},
{25, nullptr, "GetConsoleInformationUploadFlag"},
{26, nullptr, "SetConsoleInformationUploadFlag"},
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
- {29, &ISystemSettingsServer::GetNotificationSettings, "GetNotificationSettings"},
- {30, &ISystemSettingsServer::SetNotificationSettings, "SetNotificationSettings"},
- {31, &ISystemSettingsServer::GetAccountNotificationSettings, "GetAccountNotificationSettings"},
- {32, &ISystemSettingsServer::SetAccountNotificationSettings, "SetAccountNotificationSettings"},
- {35, &ISystemSettingsServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"},
- {36, &ISystemSettingsServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"},
- {37, &ISystemSettingsServer::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
- {38, &ISystemSettingsServer::GetSettingsItemValue, "GetSettingsItemValue"},
- {39, &ISystemSettingsServer::GetTvSettings, "GetTvSettings"},
- {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
+ {29, C<&ISystemSettingsServer::GetNotificationSettings>, "GetNotificationSettings"},
+ {30, C<&ISystemSettingsServer::SetNotificationSettings>, "SetNotificationSettings"},
+ {31, C<&ISystemSettingsServer::GetAccountNotificationSettings>, "GetAccountNotificationSettings"},
+ {32, C<&ISystemSettingsServer::SetAccountNotificationSettings>, "SetAccountNotificationSettings"},
+ {35, C<&ISystemSettingsServer::GetVibrationMasterVolume>, "GetVibrationMasterVolume"},
+ {36, C<&ISystemSettingsServer::SetVibrationMasterVolume>, "SetVibrationMasterVolume"},
+ {37, C<&ISystemSettingsServer::GetSettingsItemValueSize>, "GetSettingsItemValueSize"},
+ {38, C<&ISystemSettingsServer::GetSettingsItemValue>, "GetSettingsItemValue"},
+ {39, C<&ISystemSettingsServer::GetTvSettings>, "GetTvSettings"},
+ {40, C<&ISystemSettingsServer::SetTvSettings>, "SetTvSettings"},
{41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"},
- {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
- {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
- {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
- {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
- {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
- {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
+ {43, C<&ISystemSettingsServer::GetAudioOutputMode>, "GetAudioOutputMode"},
+ {44, C<&ISystemSettingsServer::SetAudioOutputMode>, "SetAudioOutputMode"},
+ {45, C<&ISystemSettingsServer::GetSpeakerAutoMuteFlag> , "GetSpeakerAutoMuteFlag"},
+ {46, C<&ISystemSettingsServer::SetSpeakerAutoMuteFlag> , "SetSpeakerAutoMuteFlag"},
+ {47, C<&ISystemSettingsServer::GetQuestFlag>, "GetQuestFlag"},
+ {48, C<&ISystemSettingsServer::SetQuestFlag>, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"},
{50, nullptr, "SetDataDeletionSettings"},
{51, nullptr, "GetInitialSystemAppletProgramId"},
{52, nullptr, "GetOverlayDispProgramId"},
- {53, &ISystemSettingsServer::GetDeviceTimeZoneLocationName, "GetDeviceTimeZoneLocationName"},
- {54, &ISystemSettingsServer::SetDeviceTimeZoneLocationName, "SetDeviceTimeZoneLocationName"},
+ {53, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationName>, "GetDeviceTimeZoneLocationName"},
+ {54, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationName>, "SetDeviceTimeZoneLocationName"},
{55, nullptr, "GetWirelessCertificationFileSize"},
{56, nullptr, "GetWirelessCertificationFile"},
- {57, &ISystemSettingsServer::SetRegionCode, "SetRegionCode"},
- {58, &ISystemSettingsServer::GetNetworkSystemClockContext, "GetNetworkSystemClockContext"},
- {59, &ISystemSettingsServer::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"},
- {60, &ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"},
- {61, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"},
- {62, &ISystemSettingsServer::GetDebugModeFlag, "GetDebugModeFlag"},
- {63, &ISystemSettingsServer::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
- {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
+ {57, C<&ISystemSettingsServer::SetRegionCode>, "SetRegionCode"},
+ {58, C<&ISystemSettingsServer::GetNetworkSystemClockContext>, "GetNetworkSystemClockContext"},
+ {59, C<&ISystemSettingsServer::SetNetworkSystemClockContext>, "SetNetworkSystemClockContext"},
+ {60, C<&ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled>, "IsUserSystemClockAutomaticCorrectionEnabled"},
+ {61, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled>, "SetUserSystemClockAutomaticCorrectionEnabled"},
+ {62, C<&ISystemSettingsServer::GetDebugModeFlag>, "GetDebugModeFlag"},
+ {63, C<&ISystemSettingsServer::GetPrimaryAlbumStorage>, "GetPrimaryAlbumStorage"},
+ {64, C<&ISystemSettingsServer::SetPrimaryAlbumStorage>, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"},
- {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
- {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
- {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
- {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
- {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
- {72, &ISystemSettingsServer::SetSleepSettings, "SetSleepSettings"},
- {73, &ISystemSettingsServer::GetWirelessLanEnableFlag, "GetWirelessLanEnableFlag"},
- {74, &ISystemSettingsServer::SetWirelessLanEnableFlag, "SetWirelessLanEnableFlag"},
- {75, &ISystemSettingsServer::GetInitialLaunchSettings, "GetInitialLaunchSettings"},
- {76, &ISystemSettingsServer::SetInitialLaunchSettings, "SetInitialLaunchSettings"},
- {77, &ISystemSettingsServer::GetDeviceNickName, "GetDeviceNickName"},
- {78, &ISystemSettingsServer::SetDeviceNickName, "SetDeviceNickName"},
- {79, &ISystemSettingsServer::GetProductModel, "GetProductModel"},
+ {67, C<&ISystemSettingsServer::GetBatteryLot>, "GetBatteryLot"},
+ {68, C<&ISystemSettingsServer::GetSerialNumber>, "GetSerialNumber"},
+ {69, C<&ISystemSettingsServer::GetNfcEnableFlag>, "GetNfcEnableFlag"},
+ {70, C<&ISystemSettingsServer::SetNfcEnableFlag>, "SetNfcEnableFlag"},
+ {71, C<&ISystemSettingsServer::GetSleepSettings>, "GetSleepSettings"},
+ {72, C<&ISystemSettingsServer::SetSleepSettings>, "SetSleepSettings"},
+ {73, C<&ISystemSettingsServer::GetWirelessLanEnableFlag>, "GetWirelessLanEnableFlag"},
+ {74, C<&ISystemSettingsServer::SetWirelessLanEnableFlag>, "SetWirelessLanEnableFlag"},
+ {75, C<&ISystemSettingsServer::GetInitialLaunchSettings>, "GetInitialLaunchSettings"},
+ {76, C<&ISystemSettingsServer::SetInitialLaunchSettings>, "SetInitialLaunchSettings"},
+ {77, C<&ISystemSettingsServer::GetDeviceNickName>, "GetDeviceNickName"},
+ {78, C<&ISystemSettingsServer::SetDeviceNickName>, "SetDeviceNickName"},
+ {79, C<&ISystemSettingsServer::GetProductModel>, "GetProductModel"},
{80, nullptr, "GetLdnChannel"},
{81, nullptr, "SetLdnChannel"},
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
@@ -176,25 +177,25 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{85, nullptr, "SetPtmBatteryLot"},
{86, nullptr, "GetPtmFuelGaugeParameter"},
{87, nullptr, "SetPtmFuelGaugeParameter"},
- {88, &ISystemSettingsServer::GetBluetoothEnableFlag, "GetBluetoothEnableFlag"},
- {89, &ISystemSettingsServer::SetBluetoothEnableFlag, "SetBluetoothEnableFlag"},
- {90, &ISystemSettingsServer::GetMiiAuthorId, "GetMiiAuthorId"},
+ {88, C<&ISystemSettingsServer::GetBluetoothEnableFlag>, "GetBluetoothEnableFlag"},
+ {89, C<&ISystemSettingsServer::SetBluetoothEnableFlag>, "SetBluetoothEnableFlag"},
+ {90, C<&ISystemSettingsServer::GetMiiAuthorId>, "GetMiiAuthorId"},
{91, nullptr, "SetShutdownRtcValue"},
{92, nullptr, "GetShutdownRtcValue"},
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"},
- {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
- {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
+ {95, C<&ISystemSettingsServer::GetAutoUpdateEnableFlag>, "GetAutoUpdateEnableFlag"},
+ {96, C<&ISystemSettingsServer::SetAutoUpdateEnableFlag>, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"},
- {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
- {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
+ {99, C<&ISystemSettingsServer::GetBatteryPercentageFlag>, "GetBatteryPercentageFlag"},
+ {100, C<&ISystemSettingsServer::SetBatteryPercentageFlag>, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"},
{103, nullptr, "GetUsbFullKeyEnableFlag"},
{104, nullptr, "SetUsbFullKeyEnableFlag"},
- {105, &ISystemSettingsServer::SetExternalSteadyClockInternalOffset, "SetExternalSteadyClockInternalOffset"},
- {106, &ISystemSettingsServer::GetExternalSteadyClockInternalOffset, "GetExternalSteadyClockInternalOffset"},
+ {105, C<&ISystemSettingsServer::SetExternalSteadyClockInternalOffset>, "SetExternalSteadyClockInternalOffset"},
+ {106, C<&ISystemSettingsServer::GetExternalSteadyClockInternalOffset>, "GetExternalSteadyClockInternalOffset"},
{107, nullptr, "GetBacklightSettingsEx"},
{108, nullptr, "SetBacklightSettingsEx"},
{109, nullptr, "GetHeadphoneVolumeWarningCount"},
@@ -208,14 +209,14 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
- {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
- {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
+ {120, C<&ISystemSettingsServer::GetPushNotificationActivityModeOnSleep>, "GetPushNotificationActivityModeOnSleep"},
+ {121, C<&ISystemSettingsServer::SetPushNotificationActivityModeOnSleep>, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"},
- {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
- {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
- {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
- {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
+ {124, C<&ISystemSettingsServer::GetErrorReportSharePermission>, "GetErrorReportSharePermission"},
+ {125, C<&ISystemSettingsServer::SetErrorReportSharePermission>, "SetErrorReportSharePermission"},
+ {126, C<&ISystemSettingsServer::GetAppletLaunchFlags>, "GetAppletLaunchFlags"},
+ {127, C<&ISystemSettingsServer::SetAppletLaunchFlags>, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
@@ -224,8 +225,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
- {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
- {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
+ {136, C<&ISystemSettingsServer::GetKeyboardLayout>, "GetKeyboardLayout"},
+ {137, C<&ISystemSettingsServer::SetKeyboardLayout>, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"},
{140, nullptr, "GetHostFsMountPoint"},
@@ -238,10 +239,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
- {150, &ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime, "GetDeviceTimeZoneLocationUpdatedTime"},
- {151, &ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime, "SetDeviceTimeZoneLocationUpdatedTime"},
- {152, &ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
- {153, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
+ {150, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime>, "GetDeviceTimeZoneLocationUpdatedTime"},
+ {151, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime>, "SetDeviceTimeZoneLocationUpdatedTime"},
+ {152, C<&ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime>, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
+ {153, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime>, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
{154, nullptr, "GetAccountOnlineStorageSettings"},
{155, nullptr, "SetAccountOnlineStorageSettings"},
{156, nullptr, "GetPctlReadyFlag"},
@@ -258,11 +259,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{167, nullptr, "SetUsb30DeviceEnableFlag"},
{168, nullptr, "GetThemeId"},
{169, nullptr, "SetThemeId"},
- {170, &ISystemSettingsServer::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"},
+ {170, C<&ISystemSettingsServer::GetChineseTraditionalInputMethod>, "GetChineseTraditionalInputMethod"},
{171, nullptr, "SetChineseTraditionalInputMethod"},
{172, nullptr, "GetPtmCycleCountReliability"},
{173, nullptr, "SetPtmCycleCountReliability"},
- {174, &ISystemSettingsServer::GetHomeMenuScheme, "GetHomeMenuScheme"},
+ {174, C<&ISystemSettingsServer::GetHomeMenuScheme>, "GetHomeMenuScheme"},
{175, nullptr, "GetThemeSettings"},
{176, nullptr, "SetThemeSettings"},
{177, nullptr, "GetThemeKey"},
@@ -273,10 +274,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{182, nullptr, "SetT"},
{183, nullptr, "GetPlatformRegion"},
{184, nullptr, "SetPlatformRegion"},
- {185, &ISystemSettingsServer::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"},
+ {185, C<&ISystemSettingsServer::GetHomeMenuSchemeModel>, "GetHomeMenuSchemeModel"},
{186, nullptr, "GetMemoryUsageRateFlag"},
- {187, &ISystemSettingsServer::GetTouchScreenMode, "GetTouchScreenMode"},
- {188, &ISystemSettingsServer::SetTouchScreenMode, "SetTouchScreenMode"},
+ {187, C<&ISystemSettingsServer::GetTouchScreenMode>, "GetTouchScreenMode"},
+ {188, C<&ISystemSettingsServer::SetTouchScreenMode>, "SetTouchScreenMode"},
{189, nullptr, "GetButtonConfigSettingsFull"},
{190, nullptr, "SetButtonConfigSettingsFull"},
{191, nullptr, "GetButtonConfigSettingsEmbedded"},
@@ -289,10 +290,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
{199, nullptr, "GetButtonConfigRegisteredSettings"},
{200, nullptr, "SetButtonConfigRegisteredSettings"},
- {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
+ {201, C<&ISystemSettingsServer::GetFieldTestingFlag>, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"},
- {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
- {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
+ {203, C<&ISystemSettingsServer::GetPanelCrcMode>, "GetPanelCrcMode"},
+ {204, C<&ISystemSettingsServer::SetPanelCrcMode>, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
@@ -422,178 +423,134 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
return true;
}
-void ISystemSettingsServer::SetLanguageCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.language_code = rp.PopEnum<LanguageCode>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, language_code={}", m_system_settings.language_code);
+Result ISystemSettingsServer::SetLanguageCode(LanguageCode language_code) {
+ LOG_INFO(Service_SET, "called, language_code={}", language_code);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.language_code = language_code;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetFirmwareVersion(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFirmwareVersion(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) {
LOG_DEBUG(Service_SET, "called");
- FirmwareVersionFormat firmware_data{};
- const auto result =
- GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(firmware_data);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version1));
}
-void ISystemSettingsServer::GetFirmwareVersion2(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFirmwareVersion2(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) {
LOG_DEBUG(Service_SET, "called");
- FirmwareVersionFormat firmware_data{};
- const auto result =
- GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(firmware_data);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version2));
}
-void ISystemSettingsServer::GetExternalSteadyClockSourceId(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
-
- Common::UUID id{};
- const auto res = GetExternalSteadyClockSourceId(id);
+Result ISystemSettingsServer::GetLockScreenFlag(Out<bool> out_lock_screen_flag) {
+ LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Common::UUID) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(id);
+ *out_lock_screen_flag = m_system_settings.lock_screen_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetExternalSteadyClockSourceId(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::SetLockScreenFlag(bool lock_screen_flag) {
+ LOG_INFO(Service_SET, "called, lock_screen_flag={}", lock_screen_flag);
- IPC::RequestParser rp{ctx};
- const auto id{rp.PopRaw<Common::UUID>()};
+ m_system_settings.lock_screen_flag = lock_screen_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
+}
- const auto res = SetExternalSteadyClockSourceId(id);
+Result ISystemSettingsServer::GetExternalSteadyClockSourceId(
+ Out<Common::UUID> out_clock_source_id) {
+ LOG_INFO(Service_SET, "called, clock_source_id={}",
+ m_private_settings.external_clock_source_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_clock_source_id = m_private_settings.external_clock_source_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetUserSystemClockContext(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
-
- Service::PSC::Time::SystemClockContext context{};
- const auto res = GetUserSystemClockContext(context);
+Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id) {
+ LOG_INFO(Service_SET, "called, clock_source_id={}", clock_source_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(context);
+ m_private_settings.external_clock_source_id = clock_source_id;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockContext(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetUserSystemClockContext(
+ Out<Service::PSC::Time::SystemClockContext> out_clock_context) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
-
- const auto res = SetUserSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_clock_context = m_system_settings.user_system_clock_context;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetLockScreenFlag(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.lock_screen_flag);
-}
+Result ISystemSettingsServer::SetUserSystemClockContext(
+ const Service::PSC::Time::SystemClockContext& clock_context) {
+ LOG_INFO(Service_SET, "called");
-void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.lock_screen_flag = rp.Pop<bool>();
+ m_system_settings.user_system_clock_context = clock_context;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAccountSettings(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::GetAccountSettings(Out<AccountSettings> out_account_settings) {
+ LOG_INFO(Service_SET, "called, account_settings_flags={}",
+ m_system_settings.account_settings.flags);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.account_settings);
+ *out_account_settings = m_system_settings.account_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAccountSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.account_settings = rp.PopRaw<AccountSettings>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, account_settings_flags={}",
- m_system_settings.account_settings.flags);
+Result ISystemSettingsServer::SetAccountSettings(AccountSettings account_settings) {
+ LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.account_settings = account_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetEulaVersions(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetEulaVersions(
+ Out<s32> out_count, OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions) {
LOG_INFO(Service_SET, "called, elements={}", m_system_settings.eula_version_count);
- ctx.WriteBuffer(m_system_settings.eula_versions);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.eula_version_count);
+ *out_count =
+ std::min(m_system_settings.eula_version_count, static_cast<s32>(out_eula_versions.size()));
+ memcpy(out_eula_versions.data(), m_system_settings.eula_versions.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(EulaVersion));
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetEulaVersions(HLERequestContext& ctx) {
- const auto elements = ctx.GetReadBufferNumElements<EulaVersion>();
- const auto buffer_data = ctx.ReadBuffer();
+Result ISystemSettingsServer::SetEulaVersions(
+ InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions) {
+ LOG_INFO(Service_SET, "called, elements={}", eula_versions.size());
- LOG_INFO(Service_SET, "called, elements={}", elements);
- ASSERT(elements <= m_system_settings.eula_versions.size());
+ ASSERT(eula_versions.size() <= m_system_settings.eula_versions.size());
- m_system_settings.eula_version_count = static_cast<u32>(elements);
- std::memcpy(&m_system_settings.eula_versions, buffer_data.data(),
- sizeof(EulaVersion) * elements);
+ m_system_settings.eula_version_count = static_cast<s32>(eula_versions.size());
+ std::memcpy(m_system_settings.eula_versions.data(), eula_versions.data(),
+ eula_versions.size() * sizeof(EulaVersion));
SetSaveNeeded();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetColorSetId(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetColorSetId(Out<ColorSet> out_color_set_id) {
LOG_DEBUG(Service_SET, "called, color_set=", m_system_settings.color_set_id);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.color_set_id);
+ *out_color_set_id = m_system_settings.color_set_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetColorSetId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.color_set_id = rp.PopEnum<ColorSet>();
- SetSaveNeeded();
-
- LOG_DEBUG(Service_SET, "called, color_set={}", m_system_settings.color_set_id);
+Result ISystemSettingsServer::SetColorSetId(ColorSet color_set_id) {
+ LOG_DEBUG(Service_SET, "called, color_set={}", color_set_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.color_set_id = color_set_id;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNotificationSettings(
+ Out<NotificationSettings> out_notification_settings) {
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
m_system_settings.notification_settings.flags.raw,
m_system_settings.notification_settings.volume,
@@ -602,77 +559,67 @@ void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) {
m_system_settings.notification_settings.stop_time.hour,
m_system_settings.notification_settings.stop_time.minute);
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.notification_settings);
+ *out_notification_settings = m_system_settings.notification_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNotificationSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.notification_settings = rp.PopRaw<NotificationSettings>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetNotificationSettings(
+ const NotificationSettings& notification_settings) {
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
- m_system_settings.notification_settings.flags.raw,
- m_system_settings.notification_settings.volume,
- m_system_settings.notification_settings.start_time.hour,
- m_system_settings.notification_settings.start_time.minute,
- m_system_settings.notification_settings.stop_time.hour,
- m_system_settings.notification_settings.stop_time.minute);
+ notification_settings.flags.raw, notification_settings.volume,
+ notification_settings.start_time.hour, notification_settings.start_time.minute,
+ notification_settings.stop_time.hour, notification_settings.stop_time.minute);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.notification_settings = notification_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAccountNotificationSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAccountNotificationSettings(
+ Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ out_account_notification_settings) {
LOG_INFO(Service_SET, "called, elements={}",
m_system_settings.account_notification_settings_count);
- ctx.WriteBuffer(m_system_settings.account_notification_settings);
+ *out_count = std::min(m_system_settings.account_notification_settings_count,
+ static_cast<s32>(out_account_notification_settings.size()));
+ memcpy(out_account_notification_settings.data(),
+ m_system_settings.account_notification_settings.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(AccountNotificationSettings));
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.account_notification_settings_count);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAccountNotificationSettings(HLERequestContext& ctx) {
- const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>();
- const auto buffer_data = ctx.ReadBuffer();
-
- LOG_INFO(Service_SET, "called, elements={}", elements);
+Result ISystemSettingsServer::SetAccountNotificationSettings(
+ InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> account_notification_settings) {
+ LOG_INFO(Service_SET, "called, elements={}", account_notification_settings.size());
- ASSERT(elements <= m_system_settings.account_notification_settings.size());
+ ASSERT(account_notification_settings.size() <=
+ m_system_settings.account_notification_settings.size());
- m_system_settings.account_notification_settings_count = static_cast<u32>(elements);
- std::memcpy(&m_system_settings.account_notification_settings, buffer_data.data(),
- elements * sizeof(AccountNotificationSettings));
+ m_system_settings.account_notification_settings_count =
+ static_cast<s32>(account_notification_settings.size());
+ std::memcpy(m_system_settings.account_notification_settings.data(),
+ account_notification_settings.data(),
+ account_notification_settings.size() * sizeof(AccountNotificationSettings));
SetSaveNeeded();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetVibrationMasterVolume(HLERequestContext& ctx) {
- f32 vibration_master_volume = {};
- const auto result = GetVibrationMasterVolume(vibration_master_volume);
+Result ISystemSettingsServer::GetVibrationMasterVolume(Out<f32> vibration_master_volume) {
+ LOG_INFO(Service_SET, "called, vibration_master_volume={}",
+ m_system_settings.vibration_master_volume);
- LOG_INFO(Service_SET, "called, master_volume={}", vibration_master_volume);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(vibration_master_volume);
+ *vibration_master_volume = m_system_settings.vibration_master_volume;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetVibrationMasterVolume(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto vibration_master_volume = rp.PopRaw<f32>();
-
- LOG_INFO(Service_SET, "called, elements={}", m_system_settings.vibration_master_volume);
+Result ISystemSettingsServer::SetVibrationMasterVolume(f32 vibration_master_volume) {
+ LOG_INFO(Service_SET, "called, vibration_master_volume={}", vibration_master_volume);
- const auto result = SetVibrationMasterVolume(vibration_master_volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ m_system_settings.vibration_master_volume = vibration_master_volume;
+ SetSaveNeeded();
+ R_SUCCEED();
}
// FIXME: implement support for the real system_settings.ini
@@ -734,55 +681,38 @@ static Settings GetSettings() {
return ret;
}
-void ISystemSettingsServer::GetSettingsItemValueSize(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called");
+Result ISystemSettingsServer::GetSettingsItemValueSize(
+ Out<u64> out_size, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) {
+ const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)};
+ const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)};
- // The category of the setting. This corresponds to the top-level keys of
- // system_settings.ini.
- const auto setting_category_buf{ctx.ReadBuffer(0)};
- const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
+ LOG_DEBUG(Service_SET, "called, category={}, name={}", setting_category, setting_name);
- // The name of the setting. This corresponds to the second-level keys of
- // system_settings.ini.
- const auto setting_name_buf{ctx.ReadBuffer(1)};
- const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
+ *out_size = 0;
auto settings{GetSettings()};
- u64 response_size{0};
-
if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) {
- response_size = settings[setting_category][setting_name].size();
+ *out_size = settings[setting_category][setting_name].size();
}
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(response_size == 0 ? ResultUnknown : ResultSuccess);
- rb.Push(response_size);
+ R_UNLESS(*out_size != 0, ResultUnknown);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) {
- // The category of the setting. This corresponds to the top-level keys of
- // system_settings.ini.
- const auto setting_category_buf{ctx.ReadBuffer(0)};
- const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
-
- // The name of the setting. This corresponds to the second-level keys of
- // system_settings.ini.
- const auto setting_name_buf{ctx.ReadBuffer(1)};
- const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
+Result ISystemSettingsServer::GetSettingsItemValue(
+ OutBuffer<BufferAttr_HipcMapAlias> out_data,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) {
+ const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)};
+ const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)};
- std::vector<u8> value;
- auto response = GetSettingsItemValue(value, setting_category, setting_name);
+ LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name);
- LOG_INFO(Service_SET, "called. category={}, name={} -- res=0x{:X}", setting_category,
- setting_name, response.raw);
-
- ctx.WriteBuffer(value.data(), value.size());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(response);
+ R_RETURN(GetSettingsItemValueImpl(out_data, setting_category, setting_name));
}
-void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) {
LOG_INFO(Service_SET,
"called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, "
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
@@ -793,371 +723,335 @@ void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) {
m_system_settings.tv_settings.tv_resolution,
m_system_settings.tv_settings.tv_underscan);
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.tv_settings);
+ *out_tv_settings = m_system_settings.tv_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.tv_settings = rp.PopRaw<TvSettings>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetTvSettings(TvSettings tv_settings) {
LOG_INFO(Service_SET,
"called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, "
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
- m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode,
- m_system_settings.tv_settings.contrast_ratio,
- m_system_settings.tv_settings.hdmi_content_type,
- m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama,
- m_system_settings.tv_settings.tv_resolution,
- m_system_settings.tv_settings.tv_underscan);
+ tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.contrast_ratio,
+ tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama,
+ tv_settings.tv_resolution, tv_settings.tv_underscan);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.tv_settings = tv_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<AudioOutputModeTarget>()};
-
- AudioOutputMode output_mode{};
- const auto result = GetAudioOutputMode(output_mode, target);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+Result ISystemSettingsServer::GetAudioOutputMode(Out<AudioOutputMode> out_output_mode,
+ AudioOutputModeTarget target) {
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ *out_output_mode = m_system_settings.audio_output_mode_hdmi;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ *out_output_mode = m_system_settings.audio_output_mode_speaker;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ *out_output_mode = m_system_settings.audio_output_mode_headphone;
+ break;
+ case AudioOutputModeTarget::Type3:
+ *out_output_mode = m_system_settings.audio_output_mode_type3;
+ break;
+ case AudioOutputModeTarget::Type4:
+ *out_output_mode = m_system_settings.audio_output_mode_type4;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.PushEnum(output_mode);
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<AudioOutputMode>()};
-
- const auto result = SetAudioOutputMode(target, output_mode);
-
+Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
+ AudioOutputMode output_mode) {
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ m_system_settings.audio_output_mode_hdmi = output_mode;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ m_system_settings.audio_output_mode_speaker = output_mode;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ m_system_settings.audio_output_mode_headphone = output_mode;
+ break;
+ case AudioOutputModeTarget::Type3:
+ m_system_settings.audio_output_mode_type3 = output_mode;
+ break;
+ case AudioOutputModeTarget::Type4:
+ m_system_settings.audio_output_mode_type4 = output_mode;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
+
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(
+ Out<bool> out_force_mute_on_headphone_removed) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
m_system_settings.force_mute_on_headphone_removed);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
+ *out_force_mute_on_headphone_removed = m_system_settings.force_mute_on_headphone_removed;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
- m_system_settings.force_mute_on_headphone_removed);
+ force_mute_on_headphone_removed);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.force_mute_on_headphone_removed = force_mute_on_headphone_removed;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetQuestFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetQuestFlag(Out<QuestFlag> out_quest_flag) {
LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.quest_flag);
+ *out_quest_flag = m_system_settings.quest_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetQuestFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.quest_flag = rp.PopEnum<QuestFlag>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetQuestFlag(QuestFlag quest_flag) {
+ LOG_INFO(Service_SET, "called, quest_flag={}", quest_flag);
- LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.quest_flag = quest_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceTimeZoneLocationName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceTimeZoneLocationName(
+ Out<Service::PSC::Time::LocationName> out_name) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::LocationName name{};
- const auto res = GetDeviceTimeZoneLocationName(name);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::LocationName>(name);
+ *out_name = m_system_settings.device_time_zone_location_name;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceTimeZoneLocationName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetDeviceTimeZoneLocationName(
+ const Service::PSC::Time::LocationName& name) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
-
- const auto res = SetDeviceTimeZoneLocationName(name);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
-}
-
-void ISystemSettingsServer::SetRegionCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.region_code = rp.PopEnum<SystemRegionCode>();
+ m_system_settings.device_time_zone_location_name = name;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, region_code={}", m_system_settings.region_code);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNetworkSystemClockContext(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::SetRegionCode(SystemRegionCode region_code) {
+ LOG_INFO(Service_SET, "called, region_code={}", region_code);
- Service::PSC::Time::SystemClockContext context{};
- const auto res = GetNetworkSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(context);
+ m_system_settings.region_code = region_code;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNetworkSystemClockContext(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNetworkSystemClockContext(
+ Out<Service::PSC::Time::SystemClockContext> out_context) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
-
- const auto res = SetNetworkSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_context = m_system_settings.network_system_clock_context;
+ R_SUCCEED();
}
-void ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetNetworkSystemClockContext(
+ const Service::PSC::Time::SystemClockContext& context) {
LOG_INFO(Service_SET, "called");
- bool enabled{};
- const auto res = IsUserSystemClockAutomaticCorrectionEnabled(enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(res);
- rb.PushRaw(enabled);
+ m_system_settings.network_system_clock_context = context;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(
+ Out<bool> out_automatic_correction_enabled) {
+ LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}",
+ m_system_settings.user_system_clock_automatic_correction_enabled);
- IPC::RequestParser rp{ctx};
- auto enabled{rp.Pop<bool>()};
+ *out_automatic_correction_enabled =
+ m_system_settings.user_system_clock_automatic_correction_enabled;
+ R_SUCCEED();
+}
- const auto res = SetUserSystemClockAutomaticCorrectionEnabled(enabled);
+Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(
+ bool automatic_correction_enabled) {
+ LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}",
+ automatic_correction_enabled);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.user_system_clock_automatic_correction_enabled = automatic_correction_enabled;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDebugModeFlag(HLERequestContext& ctx) {
- bool is_debug_mode_enabled = false;
- GetSettingsItemValue<bool>(is_debug_mode_enabled, "settings_debug", "is_debug_mode_enabled");
+Result ISystemSettingsServer::GetDebugModeFlag(Out<bool> is_debug_mode_enabled) {
+ const auto result = GetSettingsItemValueImpl<bool>(*is_debug_mode_enabled, "settings_debug",
+ "is_debug_mode_enabled");
- LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", is_debug_mode_enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_debug_mode_enabled);
+ LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", *is_debug_mode_enabled);
+ R_RETURN(result);
}
-void ISystemSettingsServer::GetPrimaryAlbumStorage(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPrimaryAlbumStorage(
+ Out<PrimaryAlbumStorage> out_primary_album_storage) {
LOG_INFO(Service_SET, "called, primary_album_storage={}",
m_system_settings.primary_album_storage);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.primary_album_storage);
+ *out_primary_album_storage = m_system_settings.primary_album_storage;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.primary_album_storage = rp.PopEnum<PrimaryAlbumStorage>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage) {
+ LOG_INFO(Service_SET, "called, primary_album_storage={}", primary_album_storage);
- LOG_INFO(Service_SET, "called, primary_album_storage={}",
- m_system_settings.primary_album_storage);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.primary_album_storage = primary_album_storage;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
- BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
-
+Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> out_battery_lot) {
LOG_INFO(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(battery_lot);
+ *out_battery_lot = {"YUZU0EMULATOR14022024"};
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
- SerialNumber console_serial = {"YUZ10012345678"};
-
+Result ISystemSettingsServer::GetSerialNumber(Out<SerialNumber> out_console_serial) {
LOG_INFO(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(console_serial);
+ *out_console_serial = {"YUZ10000000001"};
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNfcEnableFlag(Out<bool> out_nfc_enable_flag) {
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(m_system_settings.nfc_enable_flag);
+ *out_nfc_enable_flag = m_system_settings.nfc_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.nfc_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
+Result ISystemSettingsServer::SetNfcEnableFlag(bool nfc_enable_flag) {
+ LOG_INFO(Service_SET, "called, nfc_enable_flag={}", nfc_enable_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.nfc_enable_flag = nfc_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSleepSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetSleepSettings(Out<SleepSettings> out_sleep_settings) {
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
m_system_settings.sleep_settings.flags.raw,
m_system_settings.sleep_settings.handheld_sleep_plan,
m_system_settings.sleep_settings.console_sleep_plan);
- IPC::ResponseBuilder rb{ctx, 5};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.sleep_settings);
+ *out_sleep_settings = m_system_settings.sleep_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetSleepSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.sleep_settings = rp.PopRaw<SleepSettings>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetSleepSettings(SleepSettings sleep_settings) {
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
- m_system_settings.sleep_settings.flags.raw,
- m_system_settings.sleep_settings.handheld_sleep_plan,
- m_system_settings.sleep_settings.console_sleep_plan);
+ sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan,
+ sleep_settings.console_sleep_plan);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.sleep_settings = sleep_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetWirelessLanEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag) {
LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}",
m_system_settings.wireless_lan_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.wireless_lan_enable_flag);
+ *out_wireless_lan_enable_flag = m_system_settings.wireless_lan_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.wireless_lan_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}",
- m_system_settings.wireless_lan_enable_flag);
+Result ISystemSettingsServer::SetWirelessLanEnableFlag(bool wireless_lan_enable_flag) {
+ LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", wireless_lan_enable_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.wireless_lan_enable_flag = wireless_lan_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetInitialLaunchSettings(
+ Out<InitialLaunchSettings> out_initial_launch_settings) {
LOG_INFO(Service_SET, "called, flags={}, timestamp={}",
m_system_settings.initial_launch_settings_packed.flags.raw,
m_system_settings.initial_launch_settings_packed.timestamp.time_point);
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.initial_launch_settings_packed);
+ *out_initial_launch_settings = {
+ .flags = m_system_settings.initial_launch_settings_packed.flags,
+ .timestamp = m_system_settings.initial_launch_settings_packed.timestamp,
+ };
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetInitialLaunchSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto initial_launch_settings = rp.PopRaw<InitialLaunchSettings>();
+Result ISystemSettingsServer::SetInitialLaunchSettings(
+ InitialLaunchSettings initial_launch_settings) {
+ LOG_INFO(Service_SET, "called, flags={}, timestamp={}", initial_launch_settings.flags.raw,
+ initial_launch_settings.timestamp.time_point);
m_system_settings.initial_launch_settings_packed.flags = initial_launch_settings.flags;
m_system_settings.initial_launch_settings_packed.timestamp = initial_launch_settings.timestamp;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, flags={}, timestamp={}",
- m_system_settings.initial_launch_settings_packed.flags.raw,
- m_system_settings.initial_launch_settings_packed.timestamp.time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name) {
LOG_DEBUG(Service_SET, "called");
- ctx.WriteBuffer(::Settings::values.device_name.GetValue());
+ *out_device_name = {};
+ const auto device_name_buffer = ::Settings::values.device_name.GetValue().c_str();
+ memcpy(out_device_name->data(), device_name_buffer,
+ ::Settings::values.device_name.GetValue().size());
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceNickName(HLERequestContext& ctx) {
- const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer());
+Result ISystemSettingsServer::SetDeviceNickName(
+ InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer) {
+ const std::string device_name = Common::StringFromBuffer(*device_name_buffer);
LOG_INFO(Service_SET, "called, device_name={}", device_name);
::Settings::values.device_name = device_name;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetProductModel(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetProductModel(Out<u32> out_product_model) {
const u32 product_model = 1;
LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(product_model);
+
+ *out_product_model = product_model;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBluetoothEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag) {
LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}",
m_system_settings.bluetooth_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(m_system_settings.bluetooth_enable_flag);
+ *out_bluetooth_enable_flag = m_system_settings.bluetooth_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.bluetooth_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetBluetoothEnableFlag(bool bluetooth_enable_flag) {
+ LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", bluetooth_enable_flag);
- LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}",
- m_system_settings.bluetooth_enable_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.bluetooth_enable_flag = bluetooth_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetMiiAuthorId(Out<Common::UUID> out_mii_author_id) {
if (m_system_settings.mii_author_id.IsInvalid()) {
m_system_settings.mii_author_id = Common::UUID::MakeDefault();
SetSaveNeeded();
@@ -1166,282 +1060,224 @@ void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, author_id={}",
m_system_settings.mii_author_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.mii_author_id);
+ *out_mii_author_id = m_system_settings.mii_author_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag) {
LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.auto_update_enable_flag);
+ *out_auto_update_enable_flag = m_system_settings.auto_update_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetAutoUpdateEnableFlag(bool auto_update_enable_flag) {
+ LOG_INFO(Service_SET, "called, auto_update_flag={}", auto_update_enable_flag);
- LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.auto_update_enable_flag = auto_update_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag) {
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.battery_percentage_flag);
+ *out_battery_percentage_flag = m_system_settings.battery_percentage_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.battery_percentage_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
- m_system_settings.battery_percentage_flag);
+Result ISystemSettingsServer::SetBatteryPercentageFlag(bool battery_percentage_flag) {
+ LOG_INFO(Service_SET, "called, battery_percentage_flag={}", battery_percentage_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.battery_percentage_flag = battery_percentage_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called.");
-
- IPC::RequestParser rp{ctx};
- auto offset{rp.Pop<s64>()};
-
- const auto res = SetExternalSteadyClockInternalOffset(offset);
+Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) {
+ LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}", offset);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_private_settings.external_steady_clock_internal_offset = offset;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called.");
+Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(Out<s64> out_offset) {
+ LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}",
+ m_private_settings.external_steady_clock_internal_offset);
- s64 offset{};
- const auto res = GetExternalSteadyClockInternalOffset(offset);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.Push(offset);
+ *out_offset = m_private_settings.external_steady_clock_internal_offset;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(
+ Out<s32> out_push_notification_activity_mode_on_sleep) {
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
m_system_settings.push_notification_activity_mode_on_sleep);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
+ *out_push_notification_activity_mode_on_sleep =
+ m_system_settings.push_notification_activity_mode_on_sleep;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(
+ s32 push_notification_activity_mode_on_sleep) {
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
- m_system_settings.push_notification_activity_mode_on_sleep);
+ push_notification_activity_mode_on_sleep);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.push_notification_activity_mode_on_sleep =
+ push_notification_activity_mode_on_sleep;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetErrorReportSharePermission(
+ Out<ErrorReportSharePermission> out_error_report_share_permission) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.error_report_share_permission);
+ *out_error_report_share_permission = m_system_settings.error_report_share_permission;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetErrorReportSharePermission(
+ ErrorReportSharePermission error_report_share_permission) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
- m_system_settings.error_report_share_permission);
+ error_report_share_permission);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.error_report_share_permission = error_report_share_permission;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAppletLaunchFlags(Out<u32> out_applet_launch_flag) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.applet_launch_flag);
+ *out_applet_launch_flag = m_system_settings.applet_launch_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.applet_launch_flag = rp.Pop<u32>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
+Result ISystemSettingsServer::SetAppletLaunchFlags(u32 applet_launch_flag) {
+ LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.applet_launch_flag = applet_launch_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout) {
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
+ *out_keyboard_layout = m_system_settings.keyboard_layout;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
+Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout) {
+ LOG_INFO(Service_SET, "called, keyboard_layout={}", keyboard_layout);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.keyboard_layout = keyboard_layout;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::SteadyClockTimePoint time_point{};
- const auto res = GetDeviceTimeZoneLocationUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
+ *out_time_point = m_system_settings.device_time_zone_location_updated_time;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(
+ const Service::PSC::Time::SteadyClockTimePoint& time_point) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()};
-
- const auto res = SetDeviceTimeZoneLocationUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.device_time_zone_location_updated_time = time_point;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
- HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::SteadyClockTimePoint time_point{};
- const auto res = GetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
+ *out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
- HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
+ const Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()};
-
- const auto res = SetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetChineseTraditionalInputMethod(
+ Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method) {
LOG_INFO(Service_SET, "called, chinese_traditional_input_method={}",
m_system_settings.chinese_traditional_input_method);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.chinese_traditional_input_method);
+ *out_chinese_traditional_input_method = m_system_settings.chinese_traditional_input_method;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetHomeMenuScheme(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme) {
LOG_DEBUG(Service_SET, "(STUBBED) called");
- const HomeMenuScheme default_color = {
+ *out_home_menu_scheme = {
.main = 0xFF323232,
.back = 0xFF323232,
.sub = 0xFFFFFFFF,
.bezel = 0xFFFFFFFF,
.extra = 0xFF000000,
};
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(HomeMenuScheme) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw(default_color);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetHomeMenuSchemeModel(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model) {
LOG_WARNING(Service_SET, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
+ *out_home_menu_scheme_model = 0;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetTouchScreenMode(HLERequestContext& ctx) {
- TouchScreenMode touch_screen_mode{};
- auto res = GetTouchScreenMode(touch_screen_mode);
+Result ISystemSettingsServer::GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode) {
+ LOG_INFO(Service_SET, "called, touch_screen_mode={}", m_system_settings.touch_screen_mode);
- LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(res);
- rb.PushEnum(touch_screen_mode);
+ *out_touch_screen_mode = m_system_settings.touch_screen_mode;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetTouchScreenMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto touch_screen_mode = rp.PopEnum<TouchScreenMode>();
- auto res = SetTouchScreenMode(touch_screen_mode);
-
+Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) {
LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.touch_screen_mode = touch_screen_mode;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFieldTestingFlag(Out<bool> out_field_testing_flag) {
LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.field_testing_flag);
+ *out_field_testing_flag = m_system_settings.field_testing_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPanelCrcMode(Out<s32> out_panel_crc_mode) {
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.panel_crc_mode);
+ *out_panel_crc_mode = m_system_settings.panel_crc_mode;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetPanelCrcMode(s32 panel_crc_mode) {
+ LOG_INFO(Service_SET, "called, panel_crc_mode={}", panel_crc_mode);
- LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.panel_crc_mode = panel_crc_mode;
+ SetSaveNeeded();
+ R_SUCCEED();
}
void ISystemSettingsServer::SetupSettings() {
@@ -1513,9 +1349,9 @@ void ISystemSettingsServer::SetSaveNeeded() {
m_save_needed = true;
}
-Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value,
- const std::string& category,
- const std::string& name) {
+Result ISystemSettingsServer::GetSettingsItemValueImpl(std::vector<u8>& out_value,
+ const std::string& category,
+ const std::string& name) {
auto settings{GetSettings()};
R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown);
@@ -1523,184 +1359,4 @@ Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value,
R_SUCCEED();
}
-Result ISystemSettingsServer::GetVibrationMasterVolume(f32& out_volume) const {
- out_volume = m_system_settings.vibration_master_volume;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
- m_system_settings.vibration_master_volume = volume;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
- AudioOutputModeTarget target) const {
- switch (target) {
- case AudioOutputModeTarget::Hdmi:
- out_output_mode = m_system_settings.audio_output_mode_hdmi;
- break;
- case AudioOutputModeTarget::Speaker:
- out_output_mode = m_system_settings.audio_output_mode_speaker;
- break;
- case AudioOutputModeTarget::Headphone:
- out_output_mode = m_system_settings.audio_output_mode_headphone;
- break;
- case AudioOutputModeTarget::Type3:
- out_output_mode = m_system_settings.audio_output_mode_type3;
- break;
- case AudioOutputModeTarget::Type4:
- out_output_mode = m_system_settings.audio_output_mode_type4;
- break;
- default:
- LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
- }
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
- AudioOutputMode output_mode) {
- switch (target) {
- case AudioOutputModeTarget::Hdmi:
- m_system_settings.audio_output_mode_hdmi = output_mode;
- break;
- case AudioOutputModeTarget::Speaker:
- m_system_settings.audio_output_mode_speaker = output_mode;
- break;
- case AudioOutputModeTarget::Headphone:
- m_system_settings.audio_output_mode_headphone = output_mode;
- break;
- case AudioOutputModeTarget::Type3:
- m_system_settings.audio_output_mode_type3 = output_mode;
- break;
- case AudioOutputModeTarget::Type4:
- m_system_settings.audio_output_mode_type4 = output_mode;
- break;
- default:
- LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
- }
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
- is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
- m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
- out_id = m_private_settings.external_clock_source_id;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& id) {
- m_private_settings.external_clock_source_id = id;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetUserSystemClockContext(
- Service::PSC::Time::SystemClockContext& out_context) const {
- out_context = m_system_settings.user_system_clock_context;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockContext(
- const Service::PSC::Time::SystemClockContext& context) {
- m_system_settings.user_system_clock_context = context;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetDeviceTimeZoneLocationName(
- Service::PSC::Time::LocationName& out_name) const {
- out_name = m_system_settings.device_time_zone_location_name;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetDeviceTimeZoneLocationName(
- const Service::PSC::Time::LocationName& name) {
- m_system_settings.device_time_zone_location_name = name;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetNetworkSystemClockContext(
- Service::PSC::Time::SystemClockContext& out_context) const {
- out_context = m_system_settings.network_system_clock_context;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetNetworkSystemClockContext(
- const Service::PSC::Time::SystemClockContext& context) {
- m_system_settings.network_system_clock_context = context;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const {
- out_enabled = m_system_settings.user_system_clock_automatic_correction_enabled;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(bool enabled) {
- m_system_settings.user_system_clock_automatic_correction_enabled = enabled;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) {
- m_private_settings.external_steady_clock_internal_offset = offset;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(s64& out_offset) const {
- out_offset = m_private_settings.external_steady_clock_internal_offset;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const {
- out_time_point = m_system_settings.device_time_zone_location_updated_time;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& time_point) {
- m_system_settings.device_time_zone_location_updated_time = time_point;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const {
- out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
- m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const {
- touch_screen_mode = m_system_settings.touch_screen_mode;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) {
- m_system_settings.touch_screen_mode = touch_screen_mode;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
} // namespace Service::Set
diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h
index 9a3b36f0c..46e06c8ea 100644
--- a/src/core/hle/service/set/system_settings_server.h
+++ b/src/core/hle/service/set/system_settings_server.h
@@ -11,6 +11,7 @@
#include "common/polyfill_thread.h"
#include "common/uuid.h"
#include "core/hle/result.h"
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/setting_formats/appln_settings.h"
@@ -33,13 +34,14 @@ public:
explicit ISystemSettingsServer(Core::System& system_);
~ISystemSettingsServer() override;
- Result GetSettingsItemValue(std::vector<u8>& out_value, const std::string& category,
- const std::string& name);
+ Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category,
+ const std::string& name);
template <typename T>
- Result GetSettingsItemValue(T& value, const std::string& category, const std::string& name) {
+ Result GetSettingsItemValueImpl(T& value, const std::string& category,
+ const std::string& name) {
std::vector<u8> data;
- const auto result = GetSettingsItemValue(data, category, name);
+ const auto result = GetSettingsItemValueImpl(data, category, name);
if (result.IsError()) {
return result;
}
@@ -48,120 +50,114 @@ public:
return result;
}
- Result GetVibrationMasterVolume(f32& out_volume) const;
- Result SetVibrationMasterVolume(f32 volume);
- Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
+public:
+ Result SetLanguageCode(LanguageCode language_code);
+ Result GetFirmwareVersion(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data);
+ Result GetFirmwareVersion2(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data);
+ Result GetLockScreenFlag(Out<bool> out_lock_screen_flag);
+ Result SetLockScreenFlag(bool lock_screen_flag);
+ Result GetExternalSteadyClockSourceId(Out<Common::UUID> out_clock_source_id);
+ Result SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id);
+ Result GetUserSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_clock_context);
+ Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& clock_context);
+ Result GetAccountSettings(Out<AccountSettings> out_account_settings);
+ Result SetAccountSettings(AccountSettings account_settings);
+ Result GetEulaVersions(Out<s32> out_count,
+ OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions);
+ Result SetEulaVersions(InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions);
+ Result GetColorSetId(Out<ColorSet> out_color_set_id);
+ Result SetColorSetId(ColorSet color_set_id);
+ Result GetNotificationSettings(Out<NotificationSettings> out_notification_settings);
+ Result SetNotificationSettings(const NotificationSettings& notification_settings);
+ Result GetAccountNotificationSettings(
+ Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ out_account_notification_settings);
+ Result SetAccountNotificationSettings(
+ InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ account_notification_settings);
+ Result GetVibrationMasterVolume(Out<f32> vibration_master_volume);
+ Result SetVibrationMasterVolume(f32 vibration_master_volume);
+ Result GetSettingsItemValueSize(
+ Out<u64> out_size,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf);
+ Result GetSettingsItemValue(
+ OutBuffer<BufferAttr_HipcMapAlias> out_data,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer);
+ Result GetTvSettings(Out<TvSettings> out_tv_settings);
+ Result SetTvSettings(TvSettings tv_settings);
+ Result GetAudioOutputMode(Out<AudioOutputMode> out_output_mode, AudioOutputModeTarget target);
Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
- Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
- Result SetSpeakerAutoMuteFlag(bool auto_mute);
- Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
- Result SetExternalSteadyClockSourceId(const Common::UUID& id);
- Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
- Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& context);
- Result GetDeviceTimeZoneLocationName(Service::PSC::Time::LocationName& out_name) const;
+ Result GetSpeakerAutoMuteFlag(Out<bool> out_force_mute_on_headphone_removed);
+ Result SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed);
+ Result GetQuestFlag(Out<QuestFlag> out_quest_flag);
+ Result SetQuestFlag(QuestFlag quest_flag);
+ Result GetDeviceTimeZoneLocationName(Out<Service::PSC::Time::LocationName> out_name);
Result SetDeviceTimeZoneLocationName(const Service::PSC::Time::LocationName& name);
- Result GetNetworkSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
+ Result SetRegionCode(SystemRegionCode region_code);
+ Result GetNetworkSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_context);
Result SetNetworkSystemClockContext(const Service::PSC::Time::SystemClockContext& context);
- Result IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const;
- Result SetUserSystemClockAutomaticCorrectionEnabled(bool enabled);
+ Result IsUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_automatic_correction_enabled);
+ Result SetUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction_enabled);
+ Result GetDebugModeFlag(Out<bool> is_debug_mode_enabled);
+ Result GetPrimaryAlbumStorage(Out<PrimaryAlbumStorage> out_primary_album_storage);
+ Result SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage);
+ Result GetBatteryLot(Out<BatteryLot> out_battery_lot);
+ Result GetSerialNumber(Out<SerialNumber> out_console_serial);
+ Result GetNfcEnableFlag(Out<bool> out_nfc_enable_flag);
+ Result SetNfcEnableFlag(bool nfc_enable_flag);
+ Result GetSleepSettings(Out<SleepSettings> out_sleep_settings);
+ Result SetSleepSettings(SleepSettings sleep_settings);
+ Result GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag);
+ Result SetWirelessLanEnableFlag(bool wireless_lan_enable_flag);
+ Result GetInitialLaunchSettings(Out<InitialLaunchSettings> out_initial_launch_settings);
+ Result SetInitialLaunchSettings(InitialLaunchSettings initial_launch_settings);
+ Result GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name);
+ Result SetDeviceNickName(
+ InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer);
+ Result GetProductModel(Out<u32> out_product_model);
+ Result GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag);
+ Result SetBluetoothEnableFlag(bool bluetooth_enable_flag);
+ Result GetMiiAuthorId(Out<Common::UUID> out_mii_author_id);
+ Result GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag);
+ Result SetAutoUpdateEnableFlag(bool auto_update_enable_flag);
+ Result GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag);
+ Result SetBatteryPercentageFlag(bool battery_percentage_flag);
Result SetExternalSteadyClockInternalOffset(s64 offset);
- Result GetExternalSteadyClockInternalOffset(s64& out_offset) const;
+ Result GetExternalSteadyClockInternalOffset(Out<s64> out_offset);
+ Result GetPushNotificationActivityModeOnSleep(
+ Out<s32> out_push_notification_activity_mode_on_sleep);
+ Result SetPushNotificationActivityModeOnSleep(s32 push_notification_activity_mode_on_sleep);
+ Result GetErrorReportSharePermission(
+ Out<ErrorReportSharePermission> out_error_report_share_permission);
+ Result SetErrorReportSharePermission(ErrorReportSharePermission error_report_share_permission);
+ Result GetAppletLaunchFlags(Out<u32> out_applet_launch_flag);
+ Result SetAppletLaunchFlags(u32 applet_launch_flag);
+ Result GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout);
+ Result SetKeyboardLayout(KeyboardLayout keyboard_layout);
Result GetDeviceTimeZoneLocationUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const;
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetDeviceTimeZoneLocationUpdatedTime(
const Service::PSC::Time::SteadyClockTimePoint& time_point);
Result GetUserSystemClockAutomaticCorrectionUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const;
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetUserSystemClockAutomaticCorrectionUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& time_point);
- Result GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const;
+ const Service::PSC::Time::SteadyClockTimePoint& out_time_point);
+ Result GetChineseTraditionalInputMethod(
+ Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method);
+ Result GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme);
+ Result GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model);
+ Result GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode);
Result SetTouchScreenMode(TouchScreenMode touch_screen_mode);
+ Result GetFieldTestingFlag(Out<bool> out_field_testing_flag);
+ Result GetPanelCrcMode(Out<s32> out_panel_crc_mode);
+ Result SetPanelCrcMode(s32 panel_crc_mode);
private:
- void SetLanguageCode(HLERequestContext& ctx);
- void GetFirmwareVersion(HLERequestContext& ctx);
- void GetFirmwareVersion2(HLERequestContext& ctx);
- void GetLockScreenFlag(HLERequestContext& ctx);
- void SetLockScreenFlag(HLERequestContext& ctx);
- void GetExternalSteadyClockSourceId(HLERequestContext& ctx);
- void SetExternalSteadyClockSourceId(HLERequestContext& ctx);
- void GetUserSystemClockContext(HLERequestContext& ctx);
- void SetUserSystemClockContext(HLERequestContext& ctx);
- void GetAccountSettings(HLERequestContext& ctx);
- void SetAccountSettings(HLERequestContext& ctx);
- void GetEulaVersions(HLERequestContext& ctx);
- void SetEulaVersions(HLERequestContext& ctx);
- void GetColorSetId(HLERequestContext& ctx);
- void SetColorSetId(HLERequestContext& ctx);
- void GetNotificationSettings(HLERequestContext& ctx);
- void SetNotificationSettings(HLERequestContext& ctx);
- void GetAccountNotificationSettings(HLERequestContext& ctx);
- void SetAccountNotificationSettings(HLERequestContext& ctx);
- void GetVibrationMasterVolume(HLERequestContext& ctx);
- void SetVibrationMasterVolume(HLERequestContext& ctx);
- void GetSettingsItemValueSize(HLERequestContext& ctx);
- void GetSettingsItemValue(HLERequestContext& ctx);
- void GetTvSettings(HLERequestContext& ctx);
- void SetTvSettings(HLERequestContext& ctx);
- void GetAudioOutputMode(HLERequestContext& ctx);
- void SetAudioOutputMode(HLERequestContext& ctx);
- void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
- void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
- void GetDebugModeFlag(HLERequestContext& ctx);
- void GetQuestFlag(HLERequestContext& ctx);
- void SetQuestFlag(HLERequestContext& ctx);
- void GetDeviceTimeZoneLocationName(HLERequestContext& ctx);
- void SetDeviceTimeZoneLocationName(HLERequestContext& ctx);
- void SetRegionCode(HLERequestContext& ctx);
- void GetNetworkSystemClockContext(HLERequestContext& ctx);
- void SetNetworkSystemClockContext(HLERequestContext& ctx);
- void IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
- void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
- void GetPrimaryAlbumStorage(HLERequestContext& ctx);
- void SetPrimaryAlbumStorage(HLERequestContext& ctx);
- void GetBatteryLot(HLERequestContext& ctx);
- void GetSerialNumber(HLERequestContext& ctx);
- void GetNfcEnableFlag(HLERequestContext& ctx);
- void SetNfcEnableFlag(HLERequestContext& ctx);
- void GetSleepSettings(HLERequestContext& ctx);
- void SetSleepSettings(HLERequestContext& ctx);
- void GetWirelessLanEnableFlag(HLERequestContext& ctx);
- void SetWirelessLanEnableFlag(HLERequestContext& ctx);
- void GetInitialLaunchSettings(HLERequestContext& ctx);
- void SetInitialLaunchSettings(HLERequestContext& ctx);
- void GetDeviceNickName(HLERequestContext& ctx);
- void SetDeviceNickName(HLERequestContext& ctx);
- void GetProductModel(HLERequestContext& ctx);
- void GetBluetoothEnableFlag(HLERequestContext& ctx);
- void SetBluetoothEnableFlag(HLERequestContext& ctx);
- void GetMiiAuthorId(HLERequestContext& ctx);
- void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
- void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
- void GetBatteryPercentageFlag(HLERequestContext& ctx);
- void SetBatteryPercentageFlag(HLERequestContext& ctx);
- void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
- void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
- void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
- void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
- void GetErrorReportSharePermission(HLERequestContext& ctx);
- void SetErrorReportSharePermission(HLERequestContext& ctx);
- void GetAppletLaunchFlags(HLERequestContext& ctx);
- void SetAppletLaunchFlags(HLERequestContext& ctx);
- void GetKeyboardLayout(HLERequestContext& ctx);
- void SetKeyboardLayout(HLERequestContext& ctx);
- void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
- void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
- void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
- void SetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
- void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
- void GetHomeMenuScheme(HLERequestContext& ctx);
- void GetHomeMenuSchemeModel(HLERequestContext& ctx);
- void GetTouchScreenMode(HLERequestContext& ctx);
- void SetTouchScreenMode(HLERequestContext& ctx);
- void GetFieldTestingFlag(HLERequestContext& ctx);
- void GetPanelCrcMode(HLERequestContext& ctx);
- void SetPanelCrcMode(HLERequestContext& ctx);
-
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
bool StoreSettingsFile(std::filesystem::path& path, auto& settings);
void SetupSettings();
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp
new file mode 100644
index 000000000..6b0bcb536
--- /dev/null
+++ b/src/core/hle/service/vi/application_display_service.cpp
@@ -0,0 +1,302 @@
+// 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/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/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_,
+ 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"},
+ {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"},
+ {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"},
+ {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"},
+ {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"},
+ {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"},
+ {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"},
+ {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"},
+ {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"},
+ {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"},
+ {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"},
+ {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"},
+ {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"},
+ {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"},
+ {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"},
+ {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"},
+ {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"},
+ {2451, nullptr, "GetIndirectLayerImageCropMap"},
+ {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"},
+ {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"},
+ {5203, nullptr, "GetDisplayVsyncEventForDebug"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+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_container->DestroyStrayLayer(layer_id);
+ }
+}
+
+Result IApplicationDisplayService::GetRelayService(
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ 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_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_container);
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetIndirectDisplayTransactionService(
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service));
+}
+
+Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+
+ display_name[display_name.size() - 1] = '\0';
+ ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,
+ "Non-default displays aren't supported yet");
+
+ R_RETURN(m_container->OpenDisplay(out_display_id, display_name));
+}
+
+Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"}));
+}
+
+Result IApplicationDisplayService::CloseDisplay(u64 display_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->CloseDisplay(display_id));
+}
+
+Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) {
+ LOG_DEBUG(Service_VI, "called");
+
+ // This literally does nothing internally in the actual service itself,
+ // and just returns a successful result code regardless of the input.
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height,
+ u64 display_id) {
+ LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
+
+ // This only returns the fixed values of 1280x720 and makes no distinguishing
+ // between docked and undocked dimensions.
+ *out_width = static_cast<s64>(DisplayResolution::UndockedWidth);
+ *out_height = static_cast<s64>(DisplayResolution::UndockedHeight);
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id);
+
+ if (scale_mode > NintendoScaleMode::PreserveAspectRatio) {
+ LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
+ R_THROW(VI::ResultOperationFailed);
+ }
+
+ if (scale_mode != NintendoScaleMode::ScaleToWindow &&
+ scale_mode != NintendoScaleMode::PreserveAspectRatio) {
+ LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
+ R_THROW(VI::ResultNotSupported);
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::ListDisplays(
+ Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+
+ if (out_displays.size() > 0) {
+ out_displays[0] = DisplayInfo{};
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,
+ OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ DisplayName display_name, u64 layer_id,
+ ClientAppletResourceUserId aruid) {
+ display_name[display_name.size() - 1] = '\0';
+
+ LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid);
+
+ u64 display_id;
+ R_TRY(m_container->OpenDisplay(&display_id, display_name));
+
+ s32 producer_binder_id;
+ R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid));
+
+ {
+ std::scoped_lock lk{m_lock};
+ m_open_layer_ids.insert(layer_id);
+ }
+
+ android::OutputParcel parcel;
+ 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_size = buffer.size();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::CloseLayer(u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
+
+ {
+ 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_RETURN(m_container->CloseLayer(layer_id));
+}
+
+Result IApplicationDisplayService::CreateStrayLayer(
+ Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ u32 flags, u64 display_id) {
+ LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id);
+
+ s32 producer_binder_id;
+ R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id));
+
+ std::scoped_lock lk{m_lock};
+ m_stray_layer_ids.insert(*out_layer_id);
+
+ android::OutputParcel parcel;
+ 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_size = buffer.size();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+
+ {
+ 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);
+
+ std::scoped_lock lk{m_lock};
+
+ auto [it, created] = m_display_vsync_events.emplace(display_id, m_context);
+ R_UNLESS(created, VI::ResultPermissionDenied);
+
+ m_container->LinkVsyncEvent(display_id, &it->second);
+ *out_vsync_event = it->second.GetHandle();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode,
+ NintendoScaleMode mode) {
+ LOG_DEBUG(Service_VI, "called mode={}", mode);
+
+ switch (mode) {
+ case NintendoScaleMode::None:
+ *out_scaling_mode = ConvertedScaleMode::None;
+ R_SUCCEED();
+ case NintendoScaleMode::Freeze:
+ *out_scaling_mode = ConvertedScaleMode::Freeze;
+ R_SUCCEED();
+ case NintendoScaleMode::ScaleToWindow:
+ *out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
+ R_SUCCEED();
+ case NintendoScaleMode::ScaleAndCrop:
+ *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
+ R_SUCCEED();
+ case NintendoScaleMode::PreserveAspectRatio:
+ *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
+ R_SUCCEED();
+ default:
+ LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
+ R_THROW(VI::ResultOperationFailed);
+ }
+}
+
+Result IApplicationDisplayService::GetIndirectLayerImageMap(
+ Out<u64> out_size, Out<u64> out_stride,
+ OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
+ s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) {
+ LOG_WARNING(
+ Service_VI,
+ "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}",
+ width, height, indirect_layer_consumer_handle, aruid.pid);
+ *out_size = 0;
+ *out_stride = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size,
+ Out<s64> out_alignment,
+ s64 width, s64 height) {
+ LOG_DEBUG(Service_VI, "called width={}, height={}", width, height);
+
+ constexpr u64 base_size = 0x20000;
+ const auto texture_size = width * height * 4;
+
+ *out_alignment = 0x1000;
+ *out_size = (texture_size + base_size - 1) / base_size * base_size;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h
new file mode 100644
index 000000000..1bdeb8f84
--- /dev/null
+++ b/src/core/hle/service/vi/application_display_service.h
@@ -0,0 +1,81 @@
+// 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"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Nvnflinger {
+class IHOSBinderDriver;
+}
+
+namespace Service::VI {
+
+class Container;
+class IManagerDisplayService;
+class ISystemDisplayService;
+
+class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
+public:
+ IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IApplicationDisplayService() override;
+
+ 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<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);
+ Result SetDisplayEnabled(u32 state, u64 display_id);
+ Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id);
+ Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id);
+ Result ListDisplays(Out<u64> out_count,
+ OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays);
+ Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid);
+ Result CloseLayer(u64 layer_id);
+ Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size,
+ OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags,
+ u64 display_id);
+ Result DestroyStrayLayer(u64 layer_id);
+ Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event,
+ u64 display_id);
+ Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode);
+ Result GetIndirectLayerImageMap(
+ Out<u64> out_size, Out<u64> out_stride,
+ OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
+ s64 width, s64 height, u64 indirect_layer_consumer_handle,
+ ClientAppletResourceUserId aruid);
+ Result GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, Out<s64> out_alignment,
+ s64 width, s64 height);
+
+private:
+ 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};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp
new file mode 100644
index 000000000..7f35a048d
--- /dev/null
+++ b/src/core/hle/service/vi/application_root_service.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#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_,
+ 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"},
+ };
+ RegisterHandlers(functions);
+}
+
+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_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
new file mode 100644
index 000000000..15aa4483d
--- /dev/null
+++ b/src/core/hle/service/vi/application_root_service.h
@@ -0,0 +1,33 @@
+// 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"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {
+public:
+ explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IApplicationRootService() override;
+
+private:
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+private:
+ 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..9074f4ae0
--- /dev/null
+++ b/src/core/hle/service/vi/container.cpp
@@ -0,0 +1,226 @@
+// 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) { this->DestroyLayerLocked(layer.GetId()); });
+
+ 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);
+
+ s32 consumer_binder_id, producer_binder_id;
+ m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id);
+
+ auto* const layer =
+ m_layers.CreateLayer(owner_aruid, display, consumer_binder_id, producer_binder_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->CreateLayer(consumer_binder_id);
+
+ *out_layer_id = layer->GetId();
+ R_SUCCEED();
+}
+
+Result Container::DestroyLayerLocked(u64 layer_id) {
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->DestroyLayer(layer->GetConsumerBinderId());
+ m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(),
+ layer->GetProducerBinderId());
+ m_layers.DestroyLayer(layer_id);
+
+ R_SUCCEED();
+}
+
+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);
+
+ layer->Open();
+
+ if (auto* display = layer->GetDisplay(); display != nullptr) {
+ m_surface_flinger->AddLayerToDisplayStack(display->GetId(), layer->GetConsumerBinderId());
+ }
+
+ *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);
+
+ if (auto* display = layer->GetDisplay(); display != nullptr) {
+ m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(),
+ layer->GetConsumerBinderId());
+ }
+
+ layer->Close();
+
+ R_SUCCEED();
+}
+
+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..5eac4d77d
--- /dev/null
+++ b/src/core/hle/service/vi/container.h
@@ -0,0 +1,89 @@
+// 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);
+
+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..e4c9c9864
--- /dev/null
+++ b/src/core/hle/service/vi/layer.h
@@ -0,0 +1,81 @@
+// 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, s32 consumer_binder_id,
+ s32 producer_binder_id) {
+ m_id = id;
+ m_owner_aruid = owner_aruid;
+ m_display = display;
+ m_consumer_binder_id = consumer_binder_id;
+ m_producer_binder_id = producer_binder_id;
+ m_is_initialized = true;
+ }
+
+ void Finalize() {
+ m_id = {};
+ m_owner_aruid = {};
+ m_display = {};
+ m_consumer_binder_id = {};
+ m_producer_binder_id = {};
+ m_is_initialized = {};
+ }
+
+ void Open() {
+ m_is_open = true;
+ }
+
+ void Close() {
+ m_is_open = false;
+ }
+
+ 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..4afca6f40
--- /dev/null
+++ b/src/core/hle/service/vi/layer_list.h
@@ -0,0 +1,71 @@
+// 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, s32 consumer_binder_id,
+ s32 producer_binder_id) {
+ Layer* const layer = GetFreeLayer();
+ if (!layer) {
+ return nullptr;
+ }
+
+ layer->Initialize(++m_next_id, owner_aruid, display, consumer_binder_id,
+ producer_binder_id);
+ 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
new file mode 100644
index 000000000..9f856282e
--- /dev/null
+++ b/src/core/hle/service/vi/manager_display_service.cpp
@@ -0,0 +1,140 @@
+// 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/vi/container.h"
+#include "core/hle/service/vi/manager_display_service.h"
+
+namespace Service::VI {
+
+IManagerDisplayService::IManagerDisplayService(Core::System& system_,
+ 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, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"},
+ {2012, nullptr, "CreateStrayLayer"},
+ {2050, nullptr, "CreateIndirectLayer"},
+ {2051, nullptr, "DestroyIndirectLayer"},
+ {2052, nullptr, "CreateIndirectProducerEndPoint"},
+ {2053, nullptr, "DestroyIndirectProducerEndPoint"},
+ {2054, nullptr, "CreateIndirectConsumerEndPoint"},
+ {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
+ {2060, nullptr, "CreateWatermarkCompositor"},
+ {2062, nullptr, "SetWatermarkText"},
+ {2063, nullptr, "SetWatermarkLayerStacks"},
+ {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
+ {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
+ {2302, nullptr, "GetDisplayHotplugEvent"},
+ {2303, nullptr, "GetDisplayModeChangedEvent"},
+ {2402, nullptr, "GetDisplayHotplugState"},
+ {2501, nullptr, "GetCompositorErrorInfo"},
+ {2601, nullptr, "GetDisplayErrorEvent"},
+ {2701, nullptr, "GetDisplayFatalErrorEvent"},
+ {4201, nullptr, "SetDisplayAlpha"},
+ {4203, nullptr, "SetDisplayLayerStack"},
+ {4205, nullptr, "SetDisplayPowerState"},
+ {4206, nullptr, "SetDefaultDisplay"},
+ {4207, nullptr, "ResetDisplayPanel"},
+ {4208, nullptr, "SetDisplayFatalErrorEnabled"},
+ {4209, nullptr, "IsDisplayPanelOn"},
+ {4300, nullptr, "GetInternalPanelId"},
+ {6000, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"},
+ {6001, nullptr, "RemoveFromLayerStack"},
+ {6002, C<&IManagerDisplayService::SetLayerVisibility>, "SetLayerVisibility"},
+ {6003, nullptr, "SetLayerConfig"},
+ {6004, nullptr, "AttachLayerPresentationTracer"},
+ {6005, nullptr, "DetachLayerPresentationTracer"},
+ {6006, nullptr, "StartLayerPresentationRecording"},
+ {6007, nullptr, "StopLayerPresentationRecording"},
+ {6008, nullptr, "StartLayerPresentationFenceWait"},
+ {6009, nullptr, "StopLayerPresentationFenceWait"},
+ {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
+ {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
+ {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
+ {6013, nullptr, "SetLayerOpacity"},
+ {6014, nullptr, "AttachLayerWatermarkCompositor"},
+ {6015, nullptr, "DetachLayerWatermarkCompositor"},
+ {7000, nullptr, "SetContentVisibility"},
+ {8000, nullptr, "SetConductorLayer"},
+ {8001, nullptr, "SetTimestampTracking"},
+ {8100, nullptr, "SetIndirectProducerFlipOffset"},
+ {8200, nullptr, "CreateSharedBufferStaticStorage"},
+ {8201, nullptr, "CreateSharedBufferTransferMemory"},
+ {8202, nullptr, "DestroySharedBuffer"},
+ {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
+ {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
+ {8207, nullptr, "UnbindSharedLowLevelLayer"},
+ {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
+ {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
+ {8210, nullptr, "CreateSharedLayer"},
+ {8211, nullptr, "DestroySharedLayer"},
+ {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
+ {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
+ {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
+ {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
+ {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
+ {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
+ {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
+ {8223, nullptr, "RegisterSharedBufferImporterAruid"},
+ {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
+ {8227, nullptr, "CreateSharedBufferProcessHeap"},
+ {8228, nullptr, "GetSharedLayerLayerStacks"},
+ {8229, nullptr, "SetSharedLayerLayerStacks"},
+ {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
+ {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
+ {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
+ {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
+ {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
+ {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
+ {8297, nullptr, "GetSharedFrameBufferContentParameter"},
+ {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IManagerDisplayService::~IManagerDisplayService() = default;
+
+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));
+}
+
+void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) {
+ m_container->GetSharedBufferManager()->DestroySession(owner_process);
+}
+
+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) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id);
+ R_SUCCEED();
+}
+
+Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
+ 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
new file mode 100644
index 000000000..b1bdf7f41
--- /dev/null
+++ b/src/core/hle/service/vi/manager_display_service.h
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#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_, std::shared_ptr<Container> container);
+ ~IManagerDisplayService() override;
+
+ 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:
+ 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
new file mode 100644
index 000000000..0f16a15b4
--- /dev/null
+++ b/src/core/hle/service/vi/manager_root_service.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// 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"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+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"},
+ {100, nullptr, "PrepareFatal"},
+ {101, nullptr, "ShowFatal"},
+ {102, nullptr, "DrawFatalRectangle"},
+ {103, nullptr, "DrawFatalText32"},
+ };
+ RegisterHandlers(functions);
+}
+
+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_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
new file mode 100644
index 000000000..77cd32869
--- /dev/null
+++ b/src/core/hle/service/vi/manager_root_service.h
@@ -0,0 +1,32 @@
+// 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"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class IManagerRootService final : public ServiceFramework<IManagerRootService> {
+public:
+ explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IManagerRootService() override;
+
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+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
new file mode 100644
index 000000000..2b8e5f957
--- /dev/null
+++ b/src/core/hle/service/vi/service_creator.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/service_creator.h"
+#include "core/hle/service/vi/vi_results.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+static bool IsValidServiceAccess(Permission permission, Policy policy) {
+ if (permission == Permission::User) {
+ return policy == Policy::User;
+ }
+
+ if (permission == Permission::System || permission == Permission::Manager) {
+ return policy == Policy::User || policy == Policy::Compositor;
+ }
+
+ return false;
+}
+
+Result GetApplicationDisplayService(
+ std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
+ Core::System& system, std::shared_ptr<Container> container, Permission permission,
+ Policy policy) {
+
+ if (!IsValidServiceAccess(permission, policy)) {
+ LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
+ R_THROW(ResultPermissionDenied);
+ }
+
+ *out_application_display_service =
+ std::make_shared<IApplicationDisplayService>(system, std::move(container));
+ R_SUCCEED();
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h
new file mode 100644
index 000000000..c6ba1797d
--- /dev/null
+++ b/src/core/hle/service/vi/service_creator.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+
+#include "common/common_types.h"
+
+namespace Core {
+class System;
+}
+
+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, std::shared_ptr<Container> container, Permission permission,
+ Policy policy);
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp
new file mode 100644
index 000000000..12cba16fa
--- /dev/null
+++ b/src/core/hle/service/vi/shared_buffer_manager.cpp
@@ -0,0 +1,431 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <random>
+
+#include "core/core.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_system_resource.h"
+#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/pixel_format.h"
+#include "core/hle/service/nvnflinger/ui/graphic_buffer.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::VI {
+
+namespace {
+
+Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group,
+ Core::System& system, u32 size) {
+ using Core::Memory::YUZU_PAGESIZE;
+
+ // Allocate memory for the system shared buffer.
+ auto& kernel = system.Kernel();
+
+ // Hold a temporary page group reference while we try to map it.
+ auto pg = std::make_unique<Kernel::KPageGroup>(
+ kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager()));
+
+ // Allocate memory from secure pool.
+ R_TRY(kernel.MemoryManager().AllocateAndOpen(
+ pg.get(), size / YUZU_PAGESIZE,
+ Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
+ Kernel::KMemoryManager::Direction::FromBack)));
+
+ // Fill the output data with red.
+ for (auto& block : *pg) {
+ u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
+ u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
+
+ for (; start < end; start++) {
+ *start = 0xFF0000FF;
+ }
+ }
+
+ // Return the mapped page group.
+ *out_page_group = std::move(pg);
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address,
+ std::unique_ptr<Kernel::KPageGroup>& pg,
+ Kernel::KProcess* process, Core::System& system) {
+ using Core::Memory::YUZU_PAGESIZE;
+
+ auto& page_table = process->GetPageTable();
+
+ // Get bounds of where mapping is possible.
+ const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());
+ const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE;
+ const auto state = Kernel::KMemoryState::IoMemory;
+ const auto perm = Kernel::KMemoryPermission::UserReadWrite;
+ std::mt19937_64 rng{process->GetRandomEntropy(0)};
+
+ // Retry up to 64 times to map into alias code range.
+ Result res = ResultSuccess;
+ int i;
+ for (i = 0; i < 64; i++) {
+ *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE);
+ res = page_table.MapPageGroup(*out_map_address, *pg, state, perm);
+ if (R_SUCCEEDED(res)) {
+ break;
+ }
+ }
+
+ // Return failure, if necessary
+ R_UNLESS(i < 64, res);
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
+ // Create a handle.
+ Nvidia::Devices::nvmap::IocCreateParams create_params{
+ .size = size,
+ .handle = 0,
+ };
+ R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success,
+ VI::ResultOperationFailed);
+
+ // Assign the output handle.
+ *out_nv_map_handle = create_params.handle;
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) {
+ // Free the handle.
+ Nvidia::Devices::nvmap::IocFreeParams free_params{
+ .handle = handle,
+ };
+ R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success,
+ VI::ResultOperationFailed);
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
+ u32 size, Nvidia::DeviceFD nvmap_fd) {
+ // Assign the allocated memory to the handle.
+ Nvidia::Devices::nvmap::IocAllocParams alloc_params{
+ .handle = handle,
+ .heap_mask = 0,
+ .flags = {},
+ .align = 0,
+ .kind = 0,
+ .address = GetInteger(buffer),
+ };
+ R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success,
+ VI::ResultOperationFailed);
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd,
+ Common::ProcessAddress buffer, u32 size) {
+ // Get the nvmap device.
+ auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
+ ASSERT(nvmap != nullptr);
+
+ // Create a handle.
+ R_TRY(CreateNvMapHandle(out_handle, *nvmap, size));
+
+ // Ensure we maintain a clean state on failure.
+ ON_RESULT_FAILURE {
+ R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd));
+ };
+
+ // Assign the allocated memory to the handle.
+ R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));
+}
+
+void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) {
+ auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
+ ASSERT(nvmap != nullptr);
+
+ R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd));
+}
+
+constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
+constexpr u32 SharedBufferBlockLinearBpp = 4;
+
+constexpr u32 SharedBufferBlockLinearWidth = 1280;
+constexpr u32 SharedBufferBlockLinearHeight = 768;
+constexpr u32 SharedBufferBlockLinearStride =
+ SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
+constexpr u32 SharedBufferNumSlots = 7;
+
+constexpr u32 SharedBufferWidth = 1280;
+constexpr u32 SharedBufferHeight = 720;
+constexpr u32 SharedBufferAsync = false;
+
+constexpr u32 SharedBufferSlotSize =
+ SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp;
+constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots;
+
+constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
+ SharedMemoryPoolLayout layout{};
+ layout.num_slots = SharedBufferNumSlots;
+
+ for (u32 i = 0; i < SharedBufferNumSlots; i++) {
+ layout.slots[i].buffer_offset = i * SharedBufferSlotSize;
+ layout.slots[i].size = SharedBufferSlotSize;
+ layout.slots[i].width = SharedBufferWidth;
+ layout.slots[i].height = SharedBufferHeight;
+ }
+
+ return layout;
+}();
+
+void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
+ auto buffer = std::make_shared<android::NvGraphicBuffer>();
+ buffer->width = SharedBufferWidth;
+ buffer->height = SharedBufferHeight;
+ buffer->stride = SharedBufferBlockLinearStride;
+ buffer->format = SharedBufferBlockLinearFormat;
+ buffer->external_format = SharedBufferBlockLinearFormat;
+ buffer->buffer_id = handle;
+ buffer->offset = slot * SharedBufferSlotSize;
+ ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
+}
+
+} // namespace
+
+SharedBufferManager::SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv)
+ : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {}
+
+SharedBufferManager::~SharedBufferManager() = default;
+
+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.
+ const u64 aruid = owner_process->GetProcessId();
+ R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
+
+ // Allocate memory for the shared buffer if needed.
+ if (!m_buffer_page_group) {
+ R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
+ SharedBufferSize));
+
+ // Record buffer id.
+ m_buffer_id = m_next_buffer_id++;
+
+ // Record display id.
+ m_display_id = display_id;
+ }
+
+ // Map into process.
+ Common::ProcessAddress map_address{};
+ R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
+ owner_process, m_system));
+
+ // Create new session.
+ auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
+ auto& session = it->second;
+
+ auto& container = m_nvdrv->GetContainer();
+ session.session_id = container.OpenSession(owner_process);
+ session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
+
+ // Create an nvmap handle for the buffer and assign the memory to it.
+ R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
+ session.nvmap_fd, map_address, SharedBufferSize));
+
+ // Create and open a layer for the display.
+ s32 producer_binder_id;
+ R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
+ std::addressof(session.layer_id), display_id));
+
+ // Configure blending.
+ R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
+
+ // Get the producer and set preallocated buffers.
+ 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;
+ *out_layer_handle = session.layer_id;
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) {
+ std::scoped_lock lk{m_guard};
+
+ if (m_buffer_id == 0) {
+ return;
+ }
+
+ const u64 aruid = owner_process->GetProcessId();
+ const auto it = m_sessions.find(aruid);
+ if (it == m_sessions.end()) {
+ return;
+ }
+
+ auto& session = it->second;
+
+ // Destroy the layer.
+ m_container.DestroyStrayLayer(session.layer_id);
+
+ // Close nvmap handle.
+ FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
+
+ // Close nvmap device.
+ m_nvdrv->Close(session.nvmap_fd);
+
+ // Close session.
+ auto& container = m_nvdrv->GetContainer();
+ container.CloseSession(session.session_id);
+
+ // Erase.
+ m_sessions.erase(it);
+}
+
+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);
+ R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound);
+ R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound);
+
+ *out_pool_layout = SharedBufferPoolLayout;
+ *out_buffer_size = SharedBufferSize;
+ *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle;
+
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
+ std::array<s32, 4>& out_slot_indexes,
+ s64* out_target_slot, u64 layer_id) {
+ // Get the producer.
+ 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,
+ VI::ResultOperationFailed);
+
+ // Assign remaining outputs.
+ *out_target_slot = slot;
+ out_slot_indexes = {0, 1, -1, -1};
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
+ Common::Rectangle<s32> crop_region,
+ u32 transform, s32 swap_interval, u64 layer_id,
+ s64 slot) {
+ // Get the producer.
+ 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)) ==
+ android::Status::NoError,
+ VI::ResultOperationFailed);
+
+ ON_RESULT_FAILURE {
+ producer->CancelBuffer(static_cast<s32>(slot), fence);
+ };
+
+ // Queue the buffer to the producer.
+ android::QueueBufferInput input{};
+ android::QueueBufferOutput output{};
+ input.crop = crop_region;
+ 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)) ==
+ android::Status::NoError,
+ VI::ResultOperationFailed);
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
+ // 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) {
+ // Get the producer.
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
+
+ // Set the event.
+ *out_event = producer->GetNativeHandle({});
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
+ std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
+ Common::ScratchBuffer<u32> scratch;
+
+ // TODO: this could be optimized
+ s64 e = -1280 * 768 * 4;
+ for (auto& block : *m_buffer_page_group) {
+ u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
+ u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
+
+ for (; start < end; start++) {
+ *start = 0;
+
+ if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
+ *start = capture_buffer[e];
+ }
+ e++;
+ }
+
+ m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
+ m_system.GPU().InvalidateRegion(addr, end - start);
+ });
+ }
+
+ *out_was_written = true;
+ *out_layer_index = 1;
+ R_SUCCEED();
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/shared_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h
new file mode 100644
index 000000000..7c9bb7199
--- /dev/null
+++ b/src/core/hle/service/vi/shared_buffer_manager.h
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <map>
+
+#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/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;
+}
+
+union Result;
+
+namespace Service::VI {
+
+class Container;
+
+struct SharedMemorySlot {
+ u64 buffer_offset;
+ u64 size;
+ s32 width;
+ s32 height;
+};
+static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size");
+
+struct SharedMemoryPoolLayout {
+ s32 num_slots;
+ std::array<SharedMemorySlot, 0x10> slots;
+};
+static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
+
+struct SharedBufferSession;
+
+class SharedBufferManager final {
+public:
+ explicit SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv);
+ ~SharedBufferManager();
+
+ 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,
+ u64 applet_resource_user_id);
+ Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots,
+ 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:
+ u64 m_next_buffer_id = 1;
+ u64 m_display_id = 0;
+ u64 m_buffer_id = 0;
+ SharedMemoryPoolLayout m_pool_layout = {};
+ std::map<u64, SharedBufferSession> m_sessions;
+ std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
+
+ std::mutex m_guard;
+ Core::System& m_system;
+ Container& m_container;
+ const std::shared_ptr<Nvidia::Module> m_nvdrv;
+};
+
+struct SharedBufferSession {
+ Nvidia::DeviceFD nvmap_fd = {};
+ Nvidia::NvCore::SessionId session_id = {};
+ u64 layer_id = {};
+ u32 buffer_nvmap_handle = 0;
+};
+
+} // 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
new file mode 100644
index 000000000..c3c50b07b
--- /dev/null
+++ b/src/core/hle/service/vi/system_display_service.cpp
@@ -0,0 +1,169 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/hle/service/cmif_serialization.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_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1200, nullptr, "GetZOrderCountMin"},
+ {1202, nullptr, "GetZOrderCountMax"},
+ {1203, nullptr, "GetDisplayLogicalResolution"},
+ {1204, nullptr, "SetDisplayMagnification"},
+ {2201, nullptr, "SetLayerPosition"},
+ {2203, nullptr, "SetLayerSize"},
+ {2204, nullptr, "GetLayerZ"},
+ {2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"},
+ {2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"},
+ {2209, nullptr, "SetLayerAlpha"},
+ {2210, nullptr, "SetLayerPositionAndSize"},
+ {2312, nullptr, "CreateStrayLayer"},
+ {2400, nullptr, "OpenIndirectLayer"},
+ {2401, nullptr, "CloseIndirectLayer"},
+ {2402, nullptr, "FlipIndirectLayer"},
+ {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"},
+ {3001, nullptr, "ListDisplayRgbRanges"},
+ {3002, nullptr, "ListDisplayContentTypes"},
+ {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"},
+ {3201, nullptr, "SetDisplayMode"},
+ {3202, nullptr, "GetDisplayUnderscan"},
+ {3203, nullptr, "SetDisplayUnderscan"},
+ {3204, nullptr, "GetDisplayContentType"},
+ {3205, nullptr, "SetDisplayContentType"},
+ {3206, nullptr, "GetDisplayRgbRange"},
+ {3207, nullptr, "SetDisplayRgbRange"},
+ {3208, nullptr, "GetDisplayCmuMode"},
+ {3209, nullptr, "SetDisplayCmuMode"},
+ {3210, nullptr, "GetDisplayContrastRatio"},
+ {3211, nullptr, "SetDisplayContrastRatio"},
+ {3214, nullptr, "GetDisplayGamma"},
+ {3215, nullptr, "SetDisplayGamma"},
+ {3216, nullptr, "GetDisplayCmuLuma"},
+ {3217, nullptr, "SetDisplayCmuLuma"},
+ {3218, nullptr, "SetDisplayCrcMode"},
+ {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
+ {8225, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"},
+ {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"},
+ {8251, nullptr, "CloseSharedLayer"},
+ {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"},
+ {8253, nullptr, "DisconnectSharedLayer"},
+ {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"},
+ {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"},
+ {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"},
+ {8257, nullptr, "FillSharedFrameBufferColor"},
+ {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"},
+ {9000, nullptr, "GetDp2hdmiController"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+}
+
+ISystemDisplayService::~ISystemDisplayService() = default;
+
+Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value);
+ R_SUCCEED();
+}
+
+// This function currently does nothing but return a success error code in
+// the vi library itself, so do the same thing, but log out the passed in values.
+Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible);
+ R_SUCCEED();
+}
+
+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_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight);
+ } else {
+ out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight);
+ }
+
+ 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<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_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId(
+ out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid));
+}
+
+Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) {
+ LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) {
+ LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_fence,
+ Out<std::array<s32, 4>> out_slots,
+ Out<s64> out_target_slot, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer(
+ out_fence, *out_slots, out_target_slot, layer_id));
+}
+
+Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,
+ Common::Rectangle<s32> crop_region,
+ u32 window_transform, s32 swap_interval,
+ u64 layer_id, s64 surface_id) {
+ LOG_DEBUG(Service_VI, "called");
+ 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_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
new file mode 100644
index 000000000..7228d826e
--- /dev/null
+++ b/src/core/hle/service/vi/system_display_service.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/math_util.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/nvnflinger/ui/fence.h"
+#include "core/hle/service/service.h"
+#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_, std::shared_ptr<Container> container);
+ ~ISystemDisplayService() override;
+
+private:
+ Result SetLayerZ(u32 z_value, u64 layer_id);
+ Result SetLayerVisibility(bool visible, u64 layer_id);
+ 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<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
+ u64 buffer_id, ClientAppletResourceUserId aruid);
+ Result OpenSharedLayer(u64 layer_id);
+ Result ConnectSharedLayer(u64 layer_id);
+ Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event,
+ u64 layer_id);
+ Result AcquireSharedFrameBuffer(Out<android::Fence> out_fence,
+ Out<std::array<s32, 4>> out_slots, Out<s64> out_target_slot,
+ u64 layer_id);
+ 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:
+ 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
new file mode 100644
index 000000000..3489727d8
--- /dev/null
+++ b/src/core/hle/service/vi/system_root_service.cpp
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#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"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+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"},
+ };
+ RegisterHandlers(functions);
+}
+
+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_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
new file mode 100644
index 000000000..9d5aa53d3
--- /dev/null
+++ b/src/core/hle/service/vi/system_root_service.h
@@ -0,0 +1,32 @@
+// 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"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class ISystemRootService final : public ServiceFramework<ISystemRootService> {
+public:
+ explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~ISystemRootService() override;
+
+private:
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+ 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 d508ed28c..b388efaf6 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -1,974 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
-#include <array>
-#include <cstring>
-#include <memory>
-#include <optional>
-#include <type_traits>
-#include <utility>
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.h"
-#include "common/math_util.h"
-#include "common/settings.h"
-#include "common/string_util.h"
-#include "common/swap.h"
-#include "core/core_timing.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/nvdrv/devices/nvmap.h"
-#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/nvnflinger/binder.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/hos_binder_driver_server.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/nvnflinger/parcel.h"
+#include "core/core.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/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"
-#include "core/hle/service/vi/vi_m.h"
-#include "core/hle/service/vi/vi_results.h"
-#include "core/hle/service/vi/vi_s.h"
-#include "core/hle/service/vi/vi_u.h"
namespace Service::VI {
-struct DisplayInfo {
- /// The name of this particular display.
- char display_name[0x40]{"Default"};
-
- /// Whether or not the display has a limited number of layers.
- u8 has_limited_layers{1};
- INSERT_PADDING_BYTES(7);
-
- /// Indicates the total amount of layers supported by the display.
- /// @note This is only valid if has_limited_layers is set.
- u64 max_layers{1};
-
- /// Maximum width in pixels.
- u64 width{1920};
-
- /// Maximum height in pixels.
- u64 height{1080};
-};
-static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
-
-class NativeWindow final {
-public:
- constexpr explicit NativeWindow(u32 id_) : id{id_} {}
- constexpr explicit NativeWindow(const NativeWindow& other) = default;
-
-private:
- const u32 magic = 2;
- const u32 process_id = 1;
- const u64 id;
- INSERT_PADDING_WORDS(2);
- std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
- INSERT_PADDING_WORDS(2);
-};
-static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
-
-class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
-public:
- explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_)
- : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) {
- static const FunctionInfo functions[] = {
- {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
- {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
- {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"},
- {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"},
- };
- RegisterHandlers(functions);
- }
-
-private:
- void TransactParcel(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>());
- const u32 flags = rp.Pop<u32>();
-
- LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
- transaction, flags);
-
- server.TryGetProducer(id)->Transact(ctx, transaction, flags);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void AdjustRefcount(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const s32 addval = rp.PopRaw<s32>();
- const u32 type = rp.Pop<u32>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
- type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetNativeHandle(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const u32 unknown = rp.Pop<u32>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle());
- }
-
-private:
- Nvnflinger::HosBinderDriverServer& server;
-};
-
-class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
-public:
- explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
- : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1200, nullptr, "GetZOrderCountMin"},
- {1202, nullptr, "GetZOrderCountMax"},
- {1203, nullptr, "GetDisplayLogicalResolution"},
- {1204, nullptr, "SetDisplayMagnification"},
- {2201, nullptr, "SetLayerPosition"},
- {2203, nullptr, "SetLayerSize"},
- {2204, nullptr, "GetLayerZ"},
- {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
- {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
- {2209, nullptr, "SetLayerAlpha"},
- {2210, nullptr, "SetLayerPositionAndSize"},
- {2312, nullptr, "CreateStrayLayer"},
- {2400, nullptr, "OpenIndirectLayer"},
- {2401, nullptr, "CloseIndirectLayer"},
- {2402, nullptr, "FlipIndirectLayer"},
- {3000, nullptr, "ListDisplayModes"},
- {3001, nullptr, "ListDisplayRgbRanges"},
- {3002, nullptr, "ListDisplayContentTypes"},
- {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"},
- {3201, nullptr, "SetDisplayMode"},
- {3202, nullptr, "GetDisplayUnderscan"},
- {3203, nullptr, "SetDisplayUnderscan"},
- {3204, nullptr, "GetDisplayContentType"},
- {3205, nullptr, "SetDisplayContentType"},
- {3206, nullptr, "GetDisplayRgbRange"},
- {3207, nullptr, "SetDisplayRgbRange"},
- {3208, nullptr, "GetDisplayCmuMode"},
- {3209, nullptr, "SetDisplayCmuMode"},
- {3210, nullptr, "GetDisplayContrastRatio"},
- {3211, nullptr, "SetDisplayContrastRatio"},
- {3214, nullptr, "GetDisplayGamma"},
- {3215, nullptr, "SetDisplayGamma"},
- {3216, nullptr, "GetDisplayCmuLuma"},
- {3217, nullptr, "SetDisplayCmuLuma"},
- {3218, nullptr, "SetDisplayCrcMode"},
- {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
- {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"},
- {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"},
- {8251, nullptr, "CloseSharedLayer"},
- {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"},
- {8253, nullptr, "DisconnectSharedLayer"},
- {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"},
- {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"},
- {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"},
- {8257, nullptr, "FillSharedFrameBufferColor"},
- {8258, nullptr, "CancelSharedFrameBuffer"},
- {9000, nullptr, "GetDp2hdmiController"},
- };
- // clang-format on
- RegisterHandlers(functions);
- }
-
-private:
- void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 buffer_id = rp.PopRaw<u64>();
- const u64 aruid = ctx.GetPID();
-
- LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid);
-
- struct OutputParameters {
- s32 nvmap_handle;
- u64 size;
- };
-
- OutputParameters out{};
- Nvnflinger::SharedMemoryPoolLayout layout{};
- const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId(
- &out.size, &out.nvmap_handle, &layout, buffer_id, aruid);
-
- ctx.WriteBuffer(&layout, sizeof(layout));
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(result);
- rb.PushRaw(out);
- }
-
- void OpenSharedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void ConnectSharedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- Kernel::KReadableEvent* event{};
- const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(
- &event, layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(result);
- rb.PushCopyObjects(event);
- }
-
- void AcquireSharedFrameBuffer(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- struct OutputParameters {
- android::Fence fence;
- std::array<s32, 4> slots;
- s64 target_slot;
- };
- static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size");
-
- OutputParameters out{};
- const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer(
- &out.fence, out.slots, &out.target_slot, layer_id);
-
- IPC::ResponseBuilder rb{ctx, 18};
- rb.Push(result);
- rb.PushRaw(out);
- }
-
- void PresentSharedFrameBuffer(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- struct InputParameters {
- android::Fence fence;
- Common::Rectangle<s32> crop_region;
- u32 window_transform;
- s32 swap_interval;
- u64 layer_id;
- s64 surface_id;
- };
- static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size");
-
- IPC::RequestParser rp{ctx};
- auto input = rp.PopRaw<InputParameters>();
-
- const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer(
- input.fence, input.crop_region, input.window_transform, input.swap_interval,
- input.layer_id, input.surface_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void SetLayerZ(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const u64 z_value = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id,
- z_value);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- // This function currently does nothing but return a success error code in
- // the vi library itself, so do the same thing, but log out the passed in values.
- void SetLayerVisibility(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const bool visibility = rp.Pop<bool>();
-
- LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayMode(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
-
- if (Settings::IsDockedMode()) {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
- } else {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
- }
-
- rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
- rb.Push<u32>(0);
- }
-
-private:
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
-public:
- explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
- : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {200, nullptr, "AllocateProcessHeapBlock"},
- {201, nullptr, "FreeProcessHeapBlock"},
- {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
- {1102, nullptr, "GetDisplayResolution"},
- {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
- {2011, nullptr, "DestroyManagedLayer"},
- {2012, nullptr, "CreateStrayLayer"},
- {2050, nullptr, "CreateIndirectLayer"},
- {2051, nullptr, "DestroyIndirectLayer"},
- {2052, nullptr, "CreateIndirectProducerEndPoint"},
- {2053, nullptr, "DestroyIndirectProducerEndPoint"},
- {2054, nullptr, "CreateIndirectConsumerEndPoint"},
- {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
- {2060, nullptr, "CreateWatermarkCompositor"},
- {2062, nullptr, "SetWatermarkText"},
- {2063, nullptr, "SetWatermarkLayerStacks"},
- {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
- {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
- {2302, nullptr, "GetDisplayHotplugEvent"},
- {2303, nullptr, "GetDisplayModeChangedEvent"},
- {2402, nullptr, "GetDisplayHotplugState"},
- {2501, nullptr, "GetCompositorErrorInfo"},
- {2601, nullptr, "GetDisplayErrorEvent"},
- {2701, nullptr, "GetDisplayFatalErrorEvent"},
- {4201, nullptr, "SetDisplayAlpha"},
- {4203, nullptr, "SetDisplayLayerStack"},
- {4205, nullptr, "SetDisplayPowerState"},
- {4206, nullptr, "SetDefaultDisplay"},
- {4207, nullptr, "ResetDisplayPanel"},
- {4208, nullptr, "SetDisplayFatalErrorEnabled"},
- {4209, nullptr, "IsDisplayPanelOn"},
- {4300, nullptr, "GetInternalPanelId"},
- {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
- {6001, nullptr, "RemoveFromLayerStack"},
- {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
- {6003, nullptr, "SetLayerConfig"},
- {6004, nullptr, "AttachLayerPresentationTracer"},
- {6005, nullptr, "DetachLayerPresentationTracer"},
- {6006, nullptr, "StartLayerPresentationRecording"},
- {6007, nullptr, "StopLayerPresentationRecording"},
- {6008, nullptr, "StartLayerPresentationFenceWait"},
- {6009, nullptr, "StopLayerPresentationFenceWait"},
- {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
- {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
- {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
- {6013, nullptr, "SetLayerOpacity"},
- {6014, nullptr, "AttachLayerWatermarkCompositor"},
- {6015, nullptr, "DetachLayerWatermarkCompositor"},
- {7000, nullptr, "SetContentVisibility"},
- {8000, nullptr, "SetConductorLayer"},
- {8001, nullptr, "SetTimestampTracking"},
- {8100, nullptr, "SetIndirectProducerFlipOffset"},
- {8200, nullptr, "CreateSharedBufferStaticStorage"},
- {8201, nullptr, "CreateSharedBufferTransferMemory"},
- {8202, nullptr, "DestroySharedBuffer"},
- {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
- {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
- {8207, nullptr, "UnbindSharedLowLevelLayer"},
- {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
- {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
- {8210, nullptr, "CreateSharedLayer"},
- {8211, nullptr, "DestroySharedLayer"},
- {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
- {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
- {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
- {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
- {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
- {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
- {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
- {8223, nullptr, "RegisterSharedBufferImporterAruid"},
- {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
- {8227, nullptr, "CreateSharedBufferProcessHeap"},
- {8228, nullptr, "GetSharedLayerLayerStacks"},
- {8229, nullptr, "SetSharedLayerLayerStacks"},
- {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
- {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
- {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
- {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
- {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
- {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
- {8297, nullptr, "GetSharedFrameBufferContentParameter"},
- {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void CloseDisplay(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display = rp.Pop<u64>();
-
- const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- void CreateManagedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 unknown = rp.Pop<u32>();
- rp.Skip(1, false);
- const u64 display = rp.Pop<u64>();
- const u64 aruid = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI,
- "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
- unknown, display, aruid);
-
- const auto layer_id = nvnflinger.CreateLayer(display);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(*layer_id);
- }
-
- void AddToLayerStack(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 stack = rp.Pop<u32>();
- const u64 layer_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack,
- layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void SetLayerVisibility(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const bool visibility = rp.Pop<bool>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
- visibility);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
-public:
- IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_},
- hos_binder_driver_server{hos_binder_driver_server_} {
-
- static const FunctionInfo functions[] = {
- {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
- {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
- {102, &IApplicationDisplayService::GetManagerDisplayService,
- "GetManagerDisplayService"},
- {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
- "GetIndirectDisplayTransactionService"},
- {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
- {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
- {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
- {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
- {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
- {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
- {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
- {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
- {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
- {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
- {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
- {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
- {2450, &IApplicationDisplayService::GetIndirectLayerImageMap,
- "GetIndirectLayerImageMap"},
- {2451, nullptr, "GetIndirectLayerImageCropMap"},
- {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo,
- "GetIndirectLayerImageRequiredMemoryInfo"},
- {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
- {5203, nullptr, "GetDisplayVsyncEventForDebug"},
- };
- RegisterHandlers(functions);
- }
-
- ~IApplicationDisplayService() {
- for (const auto layer_id : stray_layer_ids) {
- nvnflinger.DestroyLayer(layer_id);
- }
- }
-
-private:
- enum class ConvertedScaleMode : u64 {
- Freeze = 0,
- ScaleToWindow = 1,
- ScaleAndCrop = 2,
- None = 3,
- PreserveAspectRatio = 4,
- };
-
- enum class NintendoScaleMode : u32 {
- None = 0,
- Freeze = 1,
- ScaleToWindow = 2,
- ScaleAndCrop = 3,
- PreserveAspectRatio = 4,
- };
-
- void GetRelayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
- }
-
- void GetSystemDisplayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger);
- }
-
- void GetManagerDisplayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger);
- }
-
- void GetIndirectDisplayTransactionService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
+void LoopProcess(Core::System& system, std::stop_token token) {
+ const auto container = std::make_shared<Container>(system);
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
- }
-
- void OpenDisplay(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
- const auto name_buf = rp.PopRaw<std::array<char, 0x40>>();
-
- OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()});
- }
-
- void OpenDefaultDisplay(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- OpenDisplayImpl(ctx, "Default");
- }
-
- void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) {
- const auto trim_pos = name.find('\0');
-
- if (trim_pos != std::string_view::npos) {
- name.remove_suffix(name.size() - trim_pos);
- }
-
- ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
-
- const auto display_id = nvnflinger.OpenDisplay(name);
- if (!display_id) {
- LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(*display_id);
- }
-
- void CloseDisplay(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- // This literally does nothing internally in the actual service itself,
- // and just returns a successful result code regardless of the input.
- void SetDisplayEnabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called.");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayResolution(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
-
- // This only returns the fixed values of 1280x720 and makes no distinguishing
- // between docked and undocked dimensions. We take the liberty of applying
- // the resolution scaling factor here.
- rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight));
- }
-
- void SetLayerScalingMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto scaling_mode = rp.PopEnum<NintendoScaleMode>();
- const u64 unknown = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode,
- unknown);
-
- IPC::ResponseBuilder rb{ctx, 2};
-
- if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
- LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
- rb.Push(ResultOperationFailed);
- return;
- }
-
- if (scaling_mode != NintendoScaleMode::ScaleToWindow &&
- scaling_mode != NintendoScaleMode::PreserveAspectRatio) {
- LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
- rb.Push(ResultNotSupported);
- return;
- }
-
- rb.Push(ResultSuccess);
- }
-
- void ListDisplays(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- const DisplayInfo display_info;
- ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(1);
- }
-
- void OpenLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
- const std::string display_name(Common::StringFromBuffer(name_buf));
-
- const u64 layer_id = rp.Pop<u64>();
- const u64 aruid = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
-
- const auto display_id = nvnflinger.OpenDisplay(display_name);
- if (!display_id) {
- LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- if (!nvnflinger.OpenLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to open layer which was already open");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultOperationFailed);
- return;
- }
-
- android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
-
- const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(buffer_size);
- }
-
- void CloseLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto layer_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
-
- if (!nvnflinger.CloseLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to close layer which was not open");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultOperationFailed);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void CreateStrayLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 flags = rp.Pop<u32>();
- rp.Pop<u32>(); // padding
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id);
-
- // TODO(Subv): What's the difference between a Stray and a Managed layer?
-
- const auto layer_id = nvnflinger.CreateLayer(display_id);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- stray_layer_ids.push_back(*layer_id);
- const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
-
- const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(*layer_id);
- rb.Push<u64>(buffer_size);
- }
-
- void DestroyStrayLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
- nvnflinger.DestroyLayer(layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayVsyncEvent(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
-
- Kernel::KReadableEvent* vsync_event{};
- const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id);
- if (result != ResultSuccess) {
- if (result == ResultNotFound) {
- LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
- if (vsync_event_fetched) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(VI::ResultPermissionDenied);
- return;
- }
- vsync_event_fetched = true;
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(vsync_event);
- }
-
- void ConvertScalingMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto mode = rp.PopEnum<NintendoScaleMode>();
- LOG_DEBUG(Service_VI, "called mode={}", mode);
-
- ConvertedScaleMode converted_mode{};
- const auto result = ConvertScalingModeImpl(&converted_mode, mode);
-
- if (result == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(converted_mode);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
- }
-
- void GetIndirectLayerImageMap(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto width = rp.Pop<s64>();
- const auto height = rp.Pop<s64>();
- const auto indirect_layer_consumer_handle = rp.Pop<u64>();
- const auto applet_resource_user_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI,
- "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, "
- "applet_resource_user_id={}",
- width, height, indirect_layer_consumer_handle, applet_resource_user_id);
-
- std::vector<u8> out_buffer(0x46);
- ctx.WriteBuffer(out_buffer);
-
- // TODO: Figure out what these are
-
- constexpr s64 unknown_result_1 = 0;
- constexpr s64 unknown_result_2 = 0;
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(unknown_result_1);
- rb.Push(unknown_result_2);
- rb.Push(ResultSuccess);
- }
-
- void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto width = rp.Pop<u64>();
- const auto height = rp.Pop<u64>();
- LOG_DEBUG(Service_VI, "called width={}, height={}", width, height);
-
- constexpr u64 base_size = 0x20000;
- constexpr u64 alignment = 0x1000;
- const auto texture_size = width * height * 4;
- const auto out_size = (texture_size + base_size - 1) / base_size * base_size;
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(out_size);
- rb.Push(alignment);
- }
-
- static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode,
- NintendoScaleMode mode) {
- switch (mode) {
- case NintendoScaleMode::None:
- *out_scaling_mode = ConvertedScaleMode::None;
- return ResultSuccess;
- case NintendoScaleMode::Freeze:
- *out_scaling_mode = ConvertedScaleMode::Freeze;
- return ResultSuccess;
- case NintendoScaleMode::ScaleToWindow:
- *out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
- return ResultSuccess;
- case NintendoScaleMode::ScaleAndCrop:
- *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
- return ResultSuccess;
- case NintendoScaleMode::PreserveAspectRatio:
- *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
- return ResultSuccess;
- default:
- LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
- return ResultOperationFailed;
- }
- }
-
- Nvnflinger::Nvnflinger& nvnflinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
- std::vector<u64> stray_layer_ids;
- bool vsync_event_fetched{false};
-};
-
-static bool IsValidServiceAccess(Permission permission, Policy policy) {
- if (permission == Permission::User) {
- return policy == Policy::User;
- }
-
- if (permission == Permission::System || permission == Permission::Manager) {
- return policy == Policy::User || policy == Policy::Compositor;
- }
-
- return false;
-}
-
-void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
- Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
- Permission permission) {
- IPC::RequestParser rp{ctx};
- const auto policy = rp.PopEnum<Policy>();
-
- if (!IsValidServiceAccess(permission, policy)) {
- LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultPermissionDenied);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server);
-}
-
-void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) {
auto server_manager = std::make_unique<ServerManager>(system);
+ 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:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server));
- server_manager->RegisterNamedService(
- "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server));
- server_manager->RegisterNamedService(
- "vi:u", std::make_shared<VI_U>(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 ee4bcbcfa..7c1f350d8 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -3,52 +3,14 @@
#pragma once
-#include "common/common_types.h"
+#include "common/polyfill_thread.h"
namespace Core {
class System;
}
-namespace Service {
-class HLERequestContext;
-}
-
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
-enum class DisplayResolution : u32 {
- DockedWidth = 1920,
- DockedHeight = 1080,
- UndockedWidth = 1280,
- UndockedHeight = 720,
-};
-
-/// Permission level for a particular VI service instance
-enum class Permission {
- User,
- System,
- Manager,
-};
-
-/// A policy type that may be requested via GetDisplayService and
-/// GetDisplayServiceWithProxyNameExchange
-enum class Policy {
- User,
- Compositor,
-};
-
-namespace detail {
-void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
- Nvnflinger::Nvnflinger& nv_flinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
- Permission permission);
-} // namespace detail
-
-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_m.cpp b/src/core/hle/service/vi/vi_m.cpp
deleted file mode 100644
index 0f06dc2f3..000000000
--- a/src/core/hle/service/vi/vi_m.cpp
+++ /dev/null
@@ -1,34 +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/vi/vi.h"
-#include "core/hle/service/vi/vi_m.h"
-
-namespace Service::VI {
-
-VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {2, &VI_M::GetDisplayService, "GetDisplayService"},
- {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- {100, nullptr, "PrepareFatal"},
- {101, nullptr, "ShowFatal"},
- {102, nullptr, "DrawFatalRectangle"},
- {103, nullptr, "DrawFatalText32"},
- };
- RegisterHandlers(functions);
-}
-
-VI_M::~VI_M() = default;
-
-void VI_M::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::Manager);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
deleted file mode 100644
index 9ca6f3905..000000000
--- a/src/core/hle/service/vi/vi_m.h
+++ /dev/null
@@ -1,32 +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::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_M final : public ServiceFramework<VI_M> {
-public:
- explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_M() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
deleted file mode 100644
index 77f7a88ff..000000000
--- a/src/core/hle/service/vi/vi_s.cpp
+++ /dev/null
@@ -1,30 +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/vi/vi.h"
-#include "core/hle/service/vi/vi_s.h"
-
-namespace Service::VI {
-
-VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {1, &VI_S::GetDisplayService, "GetDisplayService"},
- {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- };
- RegisterHandlers(functions);
-}
-
-VI_S::~VI_S() = default;
-
-void VI_S::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::System);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
deleted file mode 100644
index 157839c91..000000000
--- a/src/core/hle/service/vi/vi_s.h
+++ /dev/null
@@ -1,32 +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::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_S final : public ServiceFramework<VI_S> {
-public:
- explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_S() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h
new file mode 100644
index 000000000..95ff66358
--- /dev/null
+++ b/src/core/hle/service/vi/vi_types.h
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+
+namespace Service::VI {
+
+enum class DisplayResolution : u32 {
+ DockedWidth = 1920,
+ DockedHeight = 1080,
+ UndockedWidth = 1280,
+ UndockedHeight = 720,
+};
+
+/// Permission level for a particular VI service instance
+enum class Permission {
+ User,
+ System,
+ Manager,
+};
+
+/// A policy type that may be requested via GetDisplayService and
+/// GetDisplayServiceWithProxyNameExchange
+enum class Policy : u32 {
+ User,
+ Compositor,
+};
+
+enum class ConvertedScaleMode : u64 {
+ Freeze = 0,
+ ScaleToWindow = 1,
+ ScaleAndCrop = 2,
+ None = 3,
+ PreserveAspectRatio = 4,
+};
+
+enum class NintendoScaleMode : u32 {
+ None = 0,
+ Freeze = 1,
+ ScaleToWindow = 2,
+ ScaleAndCrop = 3,
+ PreserveAspectRatio = 4,
+};
+
+using DisplayName = std::array<char, 0x40>;
+
+struct DisplayInfo {
+ /// The name of this particular display.
+ DisplayName display_name{"Default"};
+
+ /// Whether or not the display has a limited number of layers.
+ u8 has_limited_layers{1};
+ INSERT_PADDING_BYTES(7);
+
+ /// Indicates the total amount of layers supported by the display.
+ /// @note This is only valid if has_limited_layers is set.
+ u64 max_layers{1};
+
+ /// Maximum width in pixels.
+ u64 width{1920};
+
+ /// Maximum height in pixels.
+ u64 height{1080};
+};
+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(s32 id_) : id{static_cast<u64>(id_)} {}
+ constexpr explicit NativeWindow(const NativeWindow& other) = default;
+
+private:
+ const u32 magic = 2;
+ const u32 process_id = 1;
+ const u64 id;
+ INSERT_PADDING_WORDS(2);
+ std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
+ INSERT_PADDING_WORDS(2);
+};
+static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
deleted file mode 100644
index 59e13c86b..000000000
--- a/src/core/hle/service/vi/vi_u.cpp
+++ /dev/null
@@ -1,30 +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/vi/vi.h"
-#include "core/hle/service/vi/vi_u.h"
-
-namespace Service::VI {
-
-VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {0, &VI_U::GetDisplayService, "GetDisplayService"},
- {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- };
- RegisterHandlers(functions);
-}
-
-VI_U::~VI_U() = default;
-
-void VI_U::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::User);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
deleted file mode 100644
index 5d9ca54c6..000000000
--- a/src/core/hle/service/vi/vi_u.h
+++ /dev/null
@@ -1,32 +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::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_U final : public ServiceFramework<VI_U> {
-public:
- explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_U() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
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
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 2a32b1276..de27ec49e 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -118,7 +118,9 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
mbedtls_sha256_starts_ret(&ctx, 0);
// Ensure we maintain a clean state on exit.
- SCOPE_EXIT({ mbedtls_sha256_free(&ctx); });
+ SCOPE_EXIT {
+ mbedtls_sha256_free(&ctx);
+ };
// Declare counters.
const size_t total_size = file->GetSize();
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index e10a4601e..8775369a4 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -831,11 +831,11 @@ struct Memory::Impl {
if (core == sys_core) [[unlikely]] {
sys_core_guard.lock();
}
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (core == sys_core) [[unlikely]] {
sys_core_guard.unlock();
}
- });
+ };
gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {
auto& current_area = rasterizer_write_areas[core];
PAddr subaddress = address >> YUZU_PAGEBITS;
@@ -866,11 +866,11 @@ struct Memory::Impl {
if (core == sys_core) [[unlikely]] {
sys_core_guard.lock();
}
- SCOPE_EXIT({
+ SCOPE_EXIT {
if (core == sys_core) [[unlikely]] {
sys_core_guard.unlock();
}
- });
+ };
auto& gpu = system.GPU();
gpu_device_memory->ApplyOpOnPointer(
p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size); });
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index b84b57d92..d8921e565 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -117,9 +117,9 @@ bool StandardVmCallbacks::IsAddressInRange(VAddr in) const {
(in < metadata.heap_extents.base ||
in >= metadata.heap_extents.base + metadata.heap_extents.size) &&
(in < metadata.alias_extents.base ||
- in >= metadata.heap_extents.base + metadata.alias_extents.size) &&
+ in >= metadata.alias_extents.base + metadata.alias_extents.size) &&
(in < metadata.aslr_extents.base ||
- in >= metadata.heap_extents.base + metadata.aslr_extents.size)) {
+ in >= metadata.aslr_extents.base + metadata.aslr_extents.size)) {
LOG_DEBUG(CheatEngine,
"Cheat attempting to access memory at invalid address={:016X}, if this "
"persists, "
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp
index f7097d01d..caceeec4f 100644
--- a/src/core/memory/dmnt_cheat_vm.cpp
+++ b/src/core/memory/dmnt_cheat_vm.cpp
@@ -224,12 +224,12 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode& out) {
// If we've ever seen a decode failure, return false.
bool valid = decode_success;
CheatVmOpcode opcode = {};
- SCOPE_EXIT({
+ SCOPE_EXIT {
decode_success &= valid;
if (valid) {
out = opcode;
}
- });
+ };
// Helper function for getting instruction dwords.
const auto GetNextDword = [&] {